Amazon S3 client based on SOAP - soap

I need a Win client for Amazon S3 that utilizes SOAP protocol for all transactions. As far as I see most solutions are REST based rather than SOAP. Any ideas?
EDIT:
Just want to clarify: please do not suggest using REST instead. I am perfectly aware of what can or cannot be done with either protocol. So if I ask for this specific solution, there is a reason for that.
What I need is a working software for Win platform that utilizes SOAP for Amazon S3, not suggestions how to do my job. Thank you.

Start Visual Studio 2008, create a new C# Windows console application.
Add the S3 WSDL as a service reference. In Solution Explorer, right click References, select Add Service Reference. Type in the S3 WSDL address in the Address box: http://s3.amazonaws.com/doc/2006-03-01/AmazonS3.wsdl. Click Go. "AmazonS3" should show in the Services box. Enter a namespace. I entered Amazon.S3. Click OK.
Modify Program.cs to look something like the following:
using System;
using System.Globalization;
using System.Text;
using System.Security.Cryptography;
using ConsoleApplication1.Amazon.S3;
namespace ConsoleApplication1 {
class Program {
private const string accessKeyId = "YOURACCESSKEYIDHERE0";
private const string secretAccessKey = "YOURSECRETACCESSKEYHEREANDYESITSTHATLONG";
public static DateTime LocalNow() {
DateTime now = DateTime.Now;
return new DateTime(now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second, now.Millisecond, DateTimeKind.Local);
}
public static string SignRequest(string secret, string operation, DateTime timestamp) {
HMACSHA1 hmac = new HMACSHA1(Encoding.UTF8.GetBytes(secret));
string isoTimeStamp = timestamp.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffZ", CultureInfo.InvariantCulture);
string signMe = "AmazonS3" + operation + isoTimeStamp;
string signature = Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(signMe)));
return signature;
}
static void Main(string[] args) {
DateTime now = LocalNow();
AmazonS3Client client = new AmazonS3Client();
var result = client.ListAllMyBuckets(
accessKeyId,
now,
SignRequest(secretAccessKey, "ListAllMyBuckets", now));
foreach (var bucket in result.Buckets) {
Console.WriteLine(bucket.Name);
}
}
}
}
If you now insert your access key ID and secret access key in the appropriate spots and run the program, you should get a listing of your S3 buckets.
The AmazonS3Client class has all the SOAP operations available as instance methods on it.
The Amazon website carries an older (VS2005 + WSE) C#/SOAP sample at http://developer.amazonwebservices.com/connect/entry.jspa?externalID=129&categoryID=47.
EDIT: posted a visual studio solution at http://flyingpies.wordpress.com/2009/08/04/the-shortest-ever-s3-csoapwcf-client/.

Related

How to use AddDigitalSignatureOriginPart (DocumentFormat.OpenXml library) to secure an Excel file?

Need to create a digital signed excel file and then validate the signature when uploaded in C#.
On its own, the SpreadsheetDocument.AddDigitalSignatureOriginPart() method does not secure an Excel file. The same is true for the corresponding methods of the WordprocessingDocument and PresentationDocument classes. Those methods only add an empty DigitalSignatureOriginPart that serves as the origin of one or more XmlSignaturePart instances, each of which contains a ds:Signature element based on the W3C Recommendation XML Signature Syntax and Processing Version 1.1 (XMLDSIG).
To secure an Excel file, or any file based on the Open Packaging Conventions (OPC), the most straightforward approach is to use the PackageDigitalSignatureManager class, which is contained in the System.IO.Packaging namespace as provided by the WindowsBase.dll assembly. Thus, if you are targeting the full .NET Framework (e.g., net471), you can use it. However, if you are targeting .Net Core, you need to implement that functionality yourself.
The following code example shows how you can use the PackageDigitalSignatureManager class:
using System;
using System.Collections.Generic;
using System.IO.Packaging;
using System.Linq;
namespace CodeSnippets.Windows.IO.Packaging
{
public static class DigitalSignatureManager
{
public static void Sign(Package package)
{
var dsm = new PackageDigitalSignatureManager(package)
{
CertificateOption = CertificateEmbeddingOption.InSignaturePart
};
List<Uri> parts = package.GetParts()
.Select(part => part.Uri)
.Concat(new[]
{
// Include the DigitalSignatureOriginPart and corresponding
// relationship part, since those will only be added when
// signing.
dsm.SignatureOrigin,
PackUriHelper.GetRelationshipPartUri(dsm.SignatureOrigin)
})
.ToList();
dsm.Sign(parts);
}
public static VerifyResult VerifySignature(Package package)
{
var dsm = new PackageDigitalSignatureManager(package);
return dsm.VerifySignatures(true);
}
}
}
In case you need to implement that functionality yourself, it helps to make yourself familiar with a number of sources:
The Digital Signing Framework of the Open Packaging Conventions
How to: Sign XML Documents with Digital Signatures
System.Security.Cryptography.Xml Namespace
Based on those sources, I created a partial sample implementation that works with .Net Core. The following snippet shows the void Sign(OpenXmlPackage, X509Certificate2) method that takes an OpenXmlPackage and an X509Certificate2 and creates a valid signature:
public static void Sign(OpenXmlPackage openXmlPackage, X509Certificate2 certificate)
{
if (openXmlPackage == null) throw new ArgumentNullException(nameof(openXmlPackage));
if (certificate == null) throw new ArgumentNullException(nameof(certificate));
RSA privateKey = certificate.GetRSAPrivateKey();
using SHA256 hashAlgorithm = SHA256.Create();
// Create KeyInfo.
var keyInfo = new KeyInfo();
keyInfo.AddClause(new KeyInfoX509Data(certificate));
// Create a Signature XmlElement.
var signedXml = new SignedXml { SigningKey = privateKey, KeyInfo = keyInfo };
signedXml.Signature.Id = Constants.PackageSignatureId;
signedXml.SignedInfo.SignatureMethod = Constants.SignatureMethod;
signedXml.AddReference(CreatePackageObjectReference());
signedXml.AddObject(CreatePackageObject(openXmlPackage.Package, hashAlgorithm));
signedXml.ComputeSignature();
XmlElement signature = signedXml.GetXml();
// Get or create the DigitalSignatureOriginPart.
DigitalSignatureOriginPart dsOriginPart =
openXmlPackage.GetPartsOfType<DigitalSignatureOriginPart>().FirstOrDefault() ??
openXmlPackage.AddNewPart<DigitalSignatureOriginPart>();
var xmlSignaturePart = dsOriginPart.AddNewPart<XmlSignaturePart>();
// Write the Signature XmlElement to the XmlSignaturePart.
using Stream stream = xmlSignaturePart.GetStream(FileMode.Create, FileAccess.Write);
using XmlWriter writer = XmlWriter.Create(stream);
signature.WriteTo(writer);
}
The full source code of the above void Sign(OpenXmlPackage, X509Certificate2) method can be found in my CodeSnippets GitHub repository. Look for the DigitalSignatureManager class in the CodeSnippets project.

How do I configure Zuul routing for URL with Token?

I am working with a microservice architecture where a Zuul gateway contacts a Eureka server to discover published microservices. I want my zuul gateway to accept path in a particular format.
It received a URL call with a member id sent as a token. Because we want to avoid sending sensitive information in URLs, these expirable tokens would be parsed by Zuul, translated to a Social Security Number, for example, and the ssn would be sent in a header.
For example, a bank acct GET:
http://zuulgateway/member/11/account/
would map to
http://microservice/account
X-MEMBER-SSN: 1112223333
My plan is to set up a "pre" Zuul filter to parse out the member token "11" and use it to get the SSN, then add it to the header.
But I'm not sure how I configure this route or if it is even possible.
zuul.routes.account.path: /member/*/**
does not achieve it. Is there some other mechanism I can use?
There are a few forum posts on the Zuul github regarding this issue but none of the solutions were working for me. I couldn't figure out why and finally realized: the hot deployment into Zuul from my Spring Tool Suite was restarting the application, but not deploying the latest changes (perhaps this is an endorsement for JRebel in the end!). Once I realized this I started experimenting with stop/deploy/start coding until I got a solution working with ZuulFilter.
The solution involves a "pre" filter which rewrites the contextURL to remove the /member/\d+/ portion of the URL so that the context can be directly mapped to the
Here is some example code:
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.stereotype.Component;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
#Component
public class SpecialFilter extends ZuulFilter {
private static final String REQUEST_URI_KEY = "requestURI";
private static final Pattern URL_PATTERN = Pattern.compile("^\\/?(\\d+)\\/(.+)$");
#Override
public boolean shouldFilter() {
return isMember(RequestContext.getCurrentContext());
}
private boolean isMember(RequestContext currentContext) {
String path = (String) currentContext.get(REQUEST_URI_KEY);
Matcher m = URL_PATTERN.matcher(path);
return m.matches();
}
#Override
public Object run() {
RequestContext context = RequestContext.getCurrentContext();
String originalRequestPath = (String) context.get(REQUEST_URI_KEY);
Matcher m = URL_PATTERN.matcher(originalRequestPath);
System.out.println("Parsing original "+originalRequestPath + " against " + URL_PATTERN.toString());
if(!m.matches()) {
System.err.println("Invalid URL");
return null;
}
String ssn = translateSSN(m.group(1));
String requestPath = m.group(2);
String modifiedRequestPath = "/" + requestPath;
context.put(REQUEST_URI_KEY, modifiedRequestPath);
//Add this header to the request
context.addZuulRequestHeader("X-SSN", ssn);
return null;
}
#Override
public String filterType() {
return "pre";
}
#Override
public int filterOrder() {
// Should proceed this filter
return FilterConstants.PRE_DECORATION_FILTER_ORDER + 1;
}
}

Trying to get an access token using restFB. but not directing

Hello i'm playing with spring boot and learning web services. I started playing with facebook graph api and using restfb. I get the access token and hard code it every time. Now i dont always want to hard code my credentials(access tokens), i want to be able to get the token when i sign in into my account without hard coding the access tokens every time i try to retrieve my photos from face and use it in my application. Has anyone worked with restfb show me an example of how to automatically get the access tokens without hard coding it. Thanks. My uri is just "localhost:8080/myapp."
#Controller
#RequestMapping("/")
public class HomeController {
#Value("#{faceBookappId['APP_KEY']}")
private static String APP_KEY;
#Value("#{faceBookappSecret['SECRET']}")
private static String APP_SECRET;
private FacebookClient.AccessToken getFaceBookUserToken(String code, String url) throws IOException {
WebRequestor web = new DefaultWebRequestor();
WebRequestor.Response accessTokens = web.executeGet("https://graph.facebook.com/oauth/access_token?client_id="+
APP_KEY+url+"&client_secret="+APP_SECRET+"&code=" + code);
return DefaultFacebookClient.AccessToken.fromQueryString(accessTokens.getBody());
}
#RequestMapping(method= RequestMethod.GET)
public String helloFaceBook(Model model) {
String url = "https://www.facebook.com/dialog/oauth?"+APP_KEY;
return "redirect"+url;
}
}
You can use the obtainUserAccessToken from the DefaultFacebookClient
FacebookClient facebookClient = new DefaultFacebookClient(Version.VERSION_2_2);
facebookClient.obtainUserAccessToken(appId, appSecret, redirectUri, verificationCode);

Servicestack (rest) incorrect WSDL with mono

I've written a simple self-hosted (in a ConsoleApplication) rest service with service stack 3.9.70.
using System;
using System.Runtime.Serialization;
// service stack support
using ServiceStack.ServiceHost;
using ServiceStack.WebHost.Endpoints;
namespace HelloWorldConsole
{
namespace DTO
{
[DataContract(Namespace = "http://localhost:8080/types")]
[Route("/hello/{Name}")]
class Hello : IReturn<HelloResponse>
{
[DataMember]
public string Name { get; set; }
}
[DataContract(Namespace = "http://localhost:8080/types")]
class HelloResponse
{
[DataMember]
public string Response { get; set; }
}
}
class HelloService : IService
{
public Object Any(DTO.Hello request)
{
return new DTO.HelloResponse { Response = "Hello " + request.Name };
}
}
public class HelloHost : AppHostHttpListenerBase
{
public HelloHost()
: base("Hello Service Self-Host",
typeof(HelloService).Assembly)
{ }
public override void Configure(Funq.Container container)
{
SetConfig(new EndpointHostConfig
{
DebugMode = true,
WsdlServiceNamespace = "http://localhost:8080/",
WsdlSoapActionNamespace = "http://localhost:8080/",
SoapServiceName = "HelloService"
});
}
}
class MainClass
{
public static void Main (string[] args)
{
string listenOn = "http://localhost:8080/";
HelloHost host = new HelloHost ();
host.Init ();
host.Start (listenOn);
Console.WriteLine ("AppHost created at {0} on {1}",
DateTime.Now, listenOn);
Console.ReadKey ();
}
}
}
Under Windows the generated WSDL is good, and if I try to create a client application and add a web reference to the soap service on localhost, I'm able to call Hello.
If I run the same code under Linux using Mono, the generated WSDL does not contain the types defined inside the DTO namespace. If I try to add a web service reference on a client, I'm not able to exploit hello method.
At this link I've read that by default the same ServiceStack Console app binary runs on both Windows/.NET and Mono/Linux as-is. I've tried to launch the binary under windows; the service runs but the generated WSDL is incorrect (without types defined in DTO namespace).
I use mono 2.10.8.1.
Does anyone have any suggestion?
I also have another question. If I use new version Servicestack last release (4.0.33) I'm not able to exploit soap endpoint.
At this link I've read that SOAP endpoints are not available when hosted on a HttpListener Host. Is it a feature introduced with new version 4.0?
Isn't there the posbility to exploit soap endpoints with servicestack releases higher than 3.9?
Any help is appreciated.
Mono has a weak and partial WCF/SOAP support which will fail to generate WSDLs for many non-trivial Service definitions. This situation may improve in the near future now that Microsoft has Open Sourced .NET server libraries, but in the interim I recommend avoiding Mono if you want to use SOAP.

Enyim Memcached client doesn't work with expiration parameter passed

when using Enyim memcached client to store data with a expire timespan, i find that it doesn't work.
Could anyone help?
In my test code, I store the date with 10 minutes expiration time, and i try to get it from cache immediately but got a null object.
Enyim.Caching.MemcachedClient client = new Enyim.Caching.MemcachedClient();
client.Store(Enyim.Caching.Memcached.StoreMode.Set, "one", 1, new TimeSpan(0, 10, 0));
object obj;
client.TryGet("one", out obj); // obj == null
Assert.AreNotEqual(null, obj); // this will fail
I'm not sure if you're being vague w/ your example or if you really are using an object type but I had the same problem using custom objects. Integers, strings, etc. would work fine but my custom object was always NULL as soon as I put it in the cache. Turns out I didn't have the Serializable attribute on my object. Once I put that on there everything worked as expected.
Hyacinthus is pretty precise on his question, the answers are somewhat irrelevant. I am having the same problem ONLY when setting an expiration, either as a Timespan or as a DateTime.
There is also an issue for this at Enyim's github https://github.com/enyim/EnyimMemcached/issues/110
We have a tweaked version at my company's codebase, but it is outdated. I will try to locate the fix and get back to this, and send a pull request to Enyim, when I find the time.
EDIT:
I also found this on github.
I can confirm that this was not happening with other build of the memcached server. I think it's a bug with this particular build:
Build with this issue:
http://www.urielkatz.com/archive/detail/memcached-64-bit-windows
Build WITHOUT this issue:
http://blog.elijaa.org/index.php?post/2010/08/25/Memcached-1.4.5-for-Windows
Care to check the server version you are using?
My initial comment still stands, as I run tests using the two different dlls, and the tweaked one works while the one shipped with CouchBase fails
Please check your server.
1.Use MemCacheD Manager
Or
2.Use telnet 127.0.0.1 11211(change to your sever setting)
and type:stats
It would show your the stats.
See the "time" item stat.
It's second format you must convert it,
Simply you can compare with "1262517674",
If smaller than "1262517674",your memcached server it too old.
Please Upgrade Or change your memcached version.
Otherwise Just change your memcached version
The answer is that memcached(windows) 1.4.4 64-bit version has this bug. If it fits your needs you can try 1.4.4 32-bit version for windows, or you can try to find another 64-bit compiled version. This problem also took my whole day and I finally installed "1.4.4 32-bit version" and viola, everything works perfect with 1.4.4. 32-bit.
Create a memcached client object is a costly operation, so try to create it on start of the application and reuse that object.
This how I initiate MemcachedClient Object and access Membese Build using Enyim client.
public class MemcachedManager
{
protected static MemcachedClient mc = null;
public MemcachedManager()
{
if (mc == null) initMemCached();
}
private void initMemCached()
{
MemcachedClientConfiguration config = new MemcachedClientConfiguration();
string ipstr = "192.168.1.1;192.168.1.2"; // List of Memcaced nodes
string[] ips = ipstr.Split(';');
foreach (string ip in ips)
{
config.Servers.Add(new IPEndPoint(IPAddress.Parse(ip), 11211));
}
config.Protocol = MemcachedProtocol.Binary;
mc = new MemcachedClient(config);
}
public void setWithTimeOut(string key, string value, int minutes)
{
mc.Store(Enyim.Caching.Memcached.StoreMode.Set, key, value, TimeSpan.FromMinutes(minutes));
}
public string getString(string key)
{
return (string)mc.Get(key);
}
public void setString(string key, string value)
{
mc.Store(Enyim.Caching.Memcached.StoreMode.Set, key, value);
}
}
you need to get a sington first.
eg:
using System;
using Enyim.Caching;
using Enyim.Caching.Memcached;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace UnitTestProject1
{
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
MemcachedClient client = MemcachedManager.Instance;//new MemcachedClient();
client.Store(StoreMode.Set, "b", "bb", new TimeSpan(1, 1, 300));
var x = client.Get("b");
client.Store(StoreMode.Set, "a", "aa");
var y = client.Get("a");
client.Store(StoreMode.Set, "c", "cc", DateTime.Now.AddSeconds(300));
var z = client.Get("c");
client.Store(StoreMode.Set, "c", "ccc");
var t = client.Get("c");
Console.WriteLine("{0},{1},{2}",x,y,z);
}
}
public static class MemcachedManager
{
private readonly static MemcachedClient _instance;
static MemcachedManager()
{
_instance = new MemcachedClient();
}
public static MemcachedClient Instance { get { return _instance; } }
}
}