I am adding KMS (SSE-KMS) encryption to an AWS S3 bucket programmatically using the AWS SDK iOS v2.6.21. I do this with the following objective-c code:
AWSS3 *awsClient = [AWSS3 S3ForKey:bucketObject.regionShortName];
AWSS3ServerSideEncryptionRule *rule= [AWSS3ServerSideEncryptionRule new];
AWSS3ServerSideEncryptionByDefault *applyServerSideEncryptionByDefault =[AWSS3ServerSideEncryptionByDefault new];applyServerSideEncryptionByDefault.SSEAlgorithm=AWSS3ServerSideEncryptionAwsKms;
applyServerSideEncryptionByDefault.KMSMasterKeyID=kmsAliasKeyId;
AWSS3ServerSideEncryptionConfiguration *configuration =
[AWSS3ServerSideEncryptionConfiguration new];
configuration.rules = #[rule];
AWSS3PutBucketEncryptionRequest *request =
[AWSS3PutBucketEncryptionRequest new];
request.bucket = bucketObject.name;
request.serverSideEncryptionConfiguration=configuration;
[awsClient putBucketEncryption:request];
}
This seemingly works and shows my bucket having default encryption. However, it does not specify that the encryption is KMS, it just shows a checkmark that encryption is on (when looking at the console).
When I programmatically check the status of the encryption it does not specify anything for SSEAlgorithm:
<AWSS3ServerSideEncryptionConfiguration: 0x604000008790> {
rules = (
"<AWSS3ServerSideEncryptionRule: 0x6040000087f0> {\n}"
);
}
I would expect the output showing SSEAlgorithm to be 2 based on how AWSS3ServerSideEncryption is defined in AWS SDK:
AWSS3ServerSideEncryption:
AWSS3ServerSideEncryptionUnknown,
AWSS3ServerSideEncryptionAES256,
AWSS3ServerSideEncryptionAwsKms,
When I compare the output when I do the same code using SSE-S3 (AWSS3ServerSideEncryptionAES256) instead and the output is:
<AWSS3ServerSideEncryptionConfiguration: 0x600000009c40> {
rules = (
"<AWSS3ServerSideEncryptionRule: 0x600000009c50> {\n
applyServerSideEncryptionByDefault = \"<AWSS3ServerSideEncryptionByDefault: 0x60000022b6a0> {\\n SSEAlgorithm = 1;\\n}\";\n}"
);
}
Can anyone see what I am missing in my request to correctly use KMS as the default encryption for the entire bucket?
Thanks. Cheers, Trond
You have setup all the objects correctly, expect for the step where you associate the encryption on the rule. See the code below for the change you need to make to get it setup correctly.
...
...
...
AWSS3ServerSideEncryptionRule *rule= [AWSS3ServerSideEncryptionRule new];
AWSS3ServerSideEncryptionByDefault *applyServerSideEncryptionByDefault =[AWSS3ServerSideEncryptionByDefault new];
applyServerSideEncryptionByDefault.SSEAlgorithm=AWSS3ServerSideEncryptionAwsKms;
applyServerSideEncryptionByDefault.KMSMasterKeyID=kmsAliasKeyId;
//Add the encryption information to the rule
rule.applyServerSideEncryptionByDefault = applyServerSideEncryptionByDefault;
AWSS3ServerSideEncryptionConfiguration *configuration =
...
...
...
Related
I am trying to use Magento's api using SOAP request in iOS.
I am using SOAPEngine to make requests and retrieve the data.
I am able to login using the following code
self.soap = [[SOAPEngine alloc] init];
self.soap.userAgent = #"SOAPEngine";
self.soap.delegate = self; // use SOAPEngineDelegate
// each single value
[self.soap setValue:#"adminUserName" forKey:#"username"];
[self.soap setValue:#"adminPassword" forKey:#"apiKey"];
// service url without ?WSDL, and you can search the soapAction in the WSDL
[self.soap requestURL:#"http://192.168.1.50/projects/usapool/api/"
soapAction:#"http://192.168.1.50/projects/usapool/api/login"];
but when I try to call the catalog_product.list as mentioned on catalog_product.list API with filters as follows
NSMutableDictionary *filterDictionary = [[NSMutableDictionary alloc] init];
[filterDictionary setValue:#"28" forKey:#"product_id"];
// each single value
[self.soap setValue:sessionId forKey:#"sessionId"];
[self.soap setValue:#"catalog_product.list" forKey:#"resourcePath"];
[self.soap setValue:filterDictionary forKey:#"filters"];
// service url without ?WSDL, and you can search the soapAction in the WSDL
[self.soap requestURL:#"http://192.168.1.50/projects/usapool/api/"
soapAction:#"http://192.168.1.50/projects/usapool/api/call"];
I get the array of all the products and filter is not applied.
Does anybody know how to apply the filters in this case?
I'm integrating Amazon SES SDK in my iOS app. I have recently observed that, I'm unable to send mails from a verified email address. if I switch to US_WEST_2 region. The problem seem to be with iOS SDK, as I'm able to send mail from Amazon Console using same mail address.
Error Message:
exception={SESMessageRejectedException { RequestId:70ed2e9e-dc16-11e3-89ca-956987a01a60, ErrorCode:MessageRejected, Message:Email address is not verified. }}, errorCode=MessageRejected}
Code:
SESManager class:
SESSendEmailRequest *ser = [[SESSendEmailRequest alloc] init] ;
ser.source = strSenderMailAddress;
ser.destination = destination;
ser.message = message;
SESSendEmailResponse *response = [[AmazonClientManager ses] sendEmail:ser];
AmazonClientManager:
+(AmazonSESClient *)ses
{
[AmazonClientManager validateCredentials];
return ses;
}
+(void)validateCredentials
{
if ([AmazonClientManager hasCredentials]) {
[AmazonClientManager clearCredentials];
ses = [[AmazonSESClient alloc] initWithAccessKey:[Lockbox stringForKey:kLockboxAmazonAccessKey] withSecretKey:[Lockbox stringForKey:kLockboxAmazonSecretKey]];
ses.endpoint = [AmazonEndpoints sesEndpoint:#"https://email.us-west-2.amazonaws.com"];
}
}
It sounds like what you are seeing is by design.
The regions are independent systems, like much of AWS.
“You must verify each sender’s email address separately for each region you want to use.”
— http://docs.aws.amazon.com/ses/latest/DeveloperGuide/regions.html
sesEndpoint: takes an AmazonRegion, which is defined as follows:
typedef enum
{
US_EAST_1 = 0,
US_WEST_1 = 1,
EU_WEST_1 = 2,
AP_SOUTHEAST_1 = 3,
AP_NORTHEAST_1 = 4,
US_WEST_2 = 5,
SA_EAST_1 = 6,
AP_SOUTHEAST_2 = 7
} AmazonRegion;
You need to change this line:
ses.endpoint = [AmazonEndpoints sesEndpoint:#"https://email.us-west-2.amazonaws.com"];
to this:
ses.endpoint = [AmazonEndpoints sesEndpoint:US_WEST_2];
When you pass an invalid region, it will default to the US East 1 region. That's why you are getting the exception.
Hope this helps,
I would suggest instead of verifying emails you look on the following issue where you can make it more Production based.
How can i send mail without verifying the recipients in amazon ses
This approach is more correct & more appropriate even though you do it for any region.
using Grails 2.3.8 and
plugins {
compile ':spring-security-core:2.0-RC2'
compile ':spring-security-oauth:2.0.2'
compile ':spring-security-oauth-facebook:0.1'
compile ':spring-security-oauth-google:0.1'
}
and the default providers setup:
oauth{
providers{
facebook{
api = org.scribe.builder.api.FacebookApi
key = '11111'
secret = '222222'
successUri = "http://localhost:8880/oauth/facebook/success"
failureUri = "http://localhost:8880/oauth/facebook/error"
callback = "http://localhost:8880/oauth/facebook/callback"
scope = 'email'
}
}
As I understood, I have to use the absolute URL's for callbacks. That is a problem, as my app is mapped to several domains, like myapp.com, myapp.de, myapp.ru etc.
Is it possible out of the box to provide the callback URL's for each domain?
TIA
so, I figured it out!
the solution contains a bit of ugliness, but works like charm:
in my Config I had to change the providers so, that the server name is reflected in provider name and callback-URLs:
oauth{
providers{
facebook{
api = org.scribe.builder.api.FacebookApi
key = '11111'
secret = '22222222'
scope = 'email'
}
'facebook_localhost'{
api = org.scribe.builder.api.FacebookApi
key = '111111'
secret = '222222222'
successUri = "http://localhost:8880/oauth/facebook_localhost/success"
failureUri = "http://localhost:8880/oauth/facebook_localhost/error"
callback = "http://localhost:8880/oauth/facebook_localhost/callback"
scope = 'email'
}
'facebook_wwwmysitenet'{
api = org.scribe.builder.api.FacebookApi
key = '9999999'
secret = '888888888888'
successUri = "http://www.mesite.net/oauth/facebook_wwwmesitenet/success"
failureUri = "http://www.mesite.net/oauth/facebook_wwwmesitenet/error"
callback = "http://www.mesite.net/oauth/facebook_wwwmesitenet/callback"
scope = 'email'
}
}
}
to make processing easier, I remove the dots from the server name.
The same I made for google.
I am trying to generate source code from a wsdl file for iOS. I've stumbled upon a couple of tools and so far wsclient++ and sudzc at least seem to work. But I need to send requests to different servers with the same soap interface, depending on the state of the iOS app.
In the source code generated by wsclient I can set the server URL via
MyWebService* ws = [MyWebService service];
// // set base url for entire application
[SoapWebService setGlobalBaseUrl: #"http://domain.com"];
NSError* error = nil;
Result* rs = [ws callMethod: p1 param2:p2 error:&error];
Which would me allow me to do something like
if(condition1) [SoapWebService setGlobalBaseUrl: #"http://betaserver.com"];
if(condition2) [SoapWebService setGlobalBaseUrl: #"http://developserver.com"];
if(condition3) [SoapWebService setGlobalBaseUrl: #"http://liveserver.com"];
Is there a way to archive something similar with the source code generated by sudzc?
As long as the soap is the same response you shouldn't have a problem using your code. There is a file that stores the server address. The code generated by sudzc can be modified to any address. I actually created a dynamic way of hitting servers. I will find the file and code I used to do this.
You can search the project for your domain you used for sudzc.
I'm not in front of a mac right now, but I will update later.
UPDATE:
Ok, so I created a settings tab and allowed the user to input a specific ip address if necessary. It saves the IP address in a dictionary and then this file retrieves it from the dictionary. I left some of my original comments and added some in the code so you can see both ways. If it confuses you let me know and I'll edit again. In my sudzc generated code I modified the file to this:
/*
wsUpdateQOH.m
The implementation classes and methods for the wsUpdateQOH web service.
Generated by SudzC.com
*/
#import "wsUpdateQOH.h"
#import "Soap.h"
#import "Settings.h"
#define URL #"http://%#/webServiceAddress/updateqoh.asmx"
/* Implementation of the service */
#implementation wsUpdateQOH
- (id) init
{
if(self = [super init])
{
// take out hard coded address and add variable to have a dynamic IP #"http://www.site.com/webServiceAddress/updateqoh.asmx"
// here is the dictionary return and format of the url string
NSString *savedValue = [[NSUserDefaults standardUserDefaults] stringForKey:#"serverIP"];
self.serviceUrl = [[NSString alloc] initWithFormat:URL, savedValue];
// uncomment for a hard coded address self.serviceUrl = #"http://%#/webServiceAddress/updateqoh.asmx";
self.namespace = #"http://tempuri.org/webServiceAddress/UpdateQOH";
self.headers = nil;
self.logging = NO;
}
return self;
}
- (id) initWithUsername: (NSString*) username andPassword: (NSString*) password {
if(self = [super initWithUsername:username andPassword:password]) {
}
return self;
}
+ (wsUpdateQOH*) service {
return [wsUpdateQOH serviceWithUsername:nil andPassword:nil];
}
+ (wsUpdateQOH*) serviceWithUsername: (NSString*) username andPassword: (NSString*) password {
return [[[wsUpdateQOH alloc] initWithUsername:username andPassword:password] autorelease];
}
// *** Below here is the soap actions ***
I'm using AWS IOS SDK and trying to list all the files in a FOLDER.
This code works to list all files etc in a BUCKET:
-(void) s3DirectoryListing: (NSString *) bucketName {
s3Client = [[AmazonS3Client alloc] initWithAccessKey:ACCESS_KEY withSecretKey:SECRET_KEY];
#try {
S3ListObjectsRequest *req = [[S3ListObjectsRequest alloc] initWithName:bucketName];
S3ListObjectsResponse *resp = [s3Client listObjects:req];
NSMutableArray* objectSummaries = resp.listObjectsResult.objectSummaries;
for (int x = 0; x < [objectSummaries count]; x++) {
NSLog(#"objectSummaries: %#",[objectSummaries objectAtIndex:x]);
}
}
#catch (NSException *exception) {
NSLog(#"Cannot list S3 %#",exception);
}
}
So if I pass a bucketName name, this works. However if I try and pass bucketName/folderName" I get an error message. This code doesn't seem to like the combination of bucket and folder path combinations.
Any ideas appreciated.
Amazon S3 is a "flat" file system, meaning it does not have physical folders. "Folders" as you know are simply prefixes added to file names.
You need to set the prefix property to your request (see the documentation)
For example, given the following set of files:
folderName1/fileNameA.txt
folderName1/fileNameB.txt
folderName2/folderName3/fileNameC.txt
If you set prefix with folderName1, and your delimiter with /, you should get only the first two entries.
Last, but not least, leave your bucketName only with the bucket name :)
More info at the S3 Developer Guide.