Amazon S3 - Method Not Allowed [closed] - amazon-web-services

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 6 days ago.
Improve this question
I'm trying to configure for the 1st time the S3 service from Amazon, but I can't upload a file, because I get the following exception (I already gave the user full access to S3, but i keep getting this):
Method Not Allowed (Service: Amazon S3; Status Code: 405; Error Code: 405 Method Not Allowed; ... )
The class below is my configuration class (the keys were changed to "xxx" for security):
public class AmazonConfiguration {
private final String ACCESS_KEY = "xxxxxxxxx";
private final String SECRET_KEY = "xxxxxxxxx";
#Bean
private AmazonS3 amazonS3client() {
//Credenciais de acesso
AWSCredentials credentials = new BasicAWSCredentials(ACCESS_KEY, SECRET_KEY);
AmazonS3 s3Client = new AmazonS3Client(credentials, new ClientConfiguration());
s3Client.setS3ClientOptions(new S3ClientOptions().withPathStyleAccess(true));
s3Client.setEndpoint("http://springmvccasadocodigo.s3-website-us-west-2.amazonaws.com/"); //springmvccasadocodigo.s3-website-sa-east-1.amazonaws.com
return s3Client;
}
}
Next class is where I try to upload the file:
#Component
public class FileServer {
#Autowired
private HttpServletRequest request;
#Autowired
private AmazonS3 s3;
public String writeAmazonS3(String baseFolder, MultipartFile multpartFile) {
try {
s3.putObject("springmvccasadocodigo",
multpartFile.getOriginalFilename(),
multpartFile.getInputStream(), new ObjectMetadata());
return "http://springmvccasadocodigo.s3-website-us-west-2.amazonaws.com/"
+ multpartFile.getOriginalFilename() + "?noAuth=true";
} catch (AmazonClientException | IOException e) {
e.printStackTrace();
throw new RuntimeException();
}
}
}

s3Client.setEndpoint("http://springmvccasadocodigo.s3-website-us-west-2.amazonaws.com/"); //springmvccasadocodigo.s3-website-sa-east-1.amazonaws.com
That's not a proper endpoint. And combining it with "path style access" is making it more difficult to debug. ("The path-style syntax... requires that you use the region-specific endpoint when attempting to access a bucket.")
Here's the list of endpoints; if your bucket is in us-west-2, the proper endpoint is s3-us-west-2.amazonaws.com. However, that's mostly useful for "off label" uses of the API, like connecting to OpenStack resources.
I believe you can simply remove those two lines ("setEndpoint" and "setS3ClientOptions").

Related

Set the AWS S3 Key header in the URI only

I have a rest api using apache camel. When I hit a post request on a route, it should get a file from S3. I am sending json data(filename, bucketName, accesskey, secretkey, region) in order to extract the file from s3. Here is the code for that ->
public static class HelloRoute extends RouteBuilder {
#Override
public void configure() {
rest("/")
.post("file-from-s3")
.route()
.setHeader(AWS2S3Constants.KEY, constant("filename"))
.to("aws2-s3://bucketnameaccessKey=INSERT&secretKey=INSERT&region=INSERT&operation=getObject")
.to("file:/tmp/")
The issue is that I don't want the .setHeader(AWS2S3Constants.KEY, constant("filename"))
part. Is there a way to remove that and put an alternate to that in the URI itself. I tried something like this ->
public static class HelloRoute extends RouteBuilder {
#Override
public void configure() {
rest("/")
.post("file-from-s3")
.route()
.to("aws2-s3://bucketnameaccessKey=INSERT&secretKey=INSERT&region=INSERT&filename=hello.txt&operation=getObject")
.to("file:/tmp/")
But this is giving me an error java.lang.IllegalArgumentException: AWS S3 Key header missing.. Is there some other way to do this?
Sometimes build an AWS Request can be complex, because of multiple options. We introduce the possibility to use a POJO as body.
Take a look at: https://camel.apache.org/components/latest/aws2-s3-component.html#_using_a_pojo_as_body

Error getting access token for service account: 401 Unauthorized when using Calendar API using service account

I have a service account with domain wide delegation setup and I'm trying to create new accounts(google-api-services-admin-directory) using the service account and then add some preset calendars(google-api-services-calendar) to the newly created accounts.
I've had no problems with the directory api. I've had to create a delegated (Admin) User using the service account and all the directory-api calls work fine.
However, I've been having trouble in getting the calendar-api calls to work.
Java dependencies:
compile group: 'com.google.auth', name: 'google-auth-library-oauth2-http', version:'0.20.0'
compile group: 'com.google.apis', name: 'google-api-services-admin-directory', version:'directory_v1-rev53-1.20.0'
compile group: 'com.google.apis', name: 'google-api-services-calendar', version:'v3-rev20200315-1.30.9'
Java code:
private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
private static final List<String> SCOPES =
Arrays.asList(DirectoryScopes.ADMIN_DIRECTORY_USER, DirectoryScopes.ADMIN_DIRECTORY_GROUP,
CalendarScopes.CALENDAR);
private static final String CREDENTIALS_FILE_PATH = "config/google-service-account-credentials.json";
.....
HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();
sourceCredentials =
ServiceAccountCredentials.fromStream(new FileInputStream(CREDENTIALS_FILE_PATH));
sourceCredentials = (ServiceAccountCredentials) sourceCredentials.createScoped(SCOPES);
.....
GoogleCredentials targetCredentials = sourceCredentials.createDelegated("newuser#email");
HttpRequestInitializer requestInitializer = new HttpCredentialsAdapter(targetCredentials);
targetCredentials.refreshIfExpired();//Not sure if this is required. It didn't help though
Calendar calendarService = new Calendar.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer).setApplicationName(MainApp.SERVICE_NAME).build();
for (String calendarKey : listOfCalendars)) {
CalendarListEntry cle = new CalendarListEntry();
cle.setId(calendarKey);
calendarService.calendarList().insert(cle).execute();//Fails with a 401
}
Stack Trace :
Caused by: java.io.IOException: Error getting access token for service account: 401 Unauthorized
at com.google.auth.oauth2.ServiceAccountCredentials.refreshAccessToken(ServiceAccountCredentials.java:444)
at com.google.auth.oauth2.OAuth2Credentials.refresh(OAuth2Credentials.java:157)
at com.google.auth.oauth2.OAuth2Credentials.refreshIfExpired(OAuth2Credentials.java:174)
at myApp.GSuiteSDKHelper.updateDefaultCalendars(GSuiteSDKHelper.java:169)
... 65 more
Caused by: com.google.api.client.http.HttpResponseException: 401 Unauthorized
at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:1113)
at com.google.auth.oauth2.ServiceAccountCredentials.refreshAccessToken(ServiceAccountCredentials.java:441)
... 68 mo
And the interesting part is that the error is intermittent. After a redeploy, I can always get my first attempt to work. Following that, it is a hit or miss.
I did add the service account to the calendars that I'm trying to add and also ensure the service account is an "owner" on the calendars.
Something similar happened to me, in my case I could solve it by adding the scopes: "https://www.googleapis.com/auth/userinfo.email","https://www.googleapis.com/auth/userinfo.profile"

C# Webclient Post to AWS API Gateway Endpoint

I am having some problems attempting to post to an API gateway endpoint.
On my API gateway I have my gateway all set up, and tested via the tool and am getting results and can verify that the step function is in fact executing the request appropriately.
{
"executionArn": "arn:aws:states:us-east-2:xxxxxxxxxxxx:execution:DevStateMachine-XXXXXXXXXXX:c9047982-e7f8-4b72-98d3-281db0eb4c30",
"startDate": 1531170720.489
}
I have set up a Stage for this for my dev environment and all looks good there as well. where I am given a URL to post against.
https://xxxxxxxxxx.execute-api.us-east-2.amazonaws.com/dev/assignments
In my c# code I have the web client defined as follows:
public Guid QueueAssignment(AssignmentDTO assignment)
{
using (var client = new HttpClient())
{
var data = JsonConvert.SerializeObject(assignment);
var content = new StringContent(data);
var uri = "https://xxxxxxxxxx.execute-api.us-east-2.amazonaws.com/dev/assignments"
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
var response = client.PostAsync(uri, content).Result;
if (response.IsSuccessStatusCode)
{
_logger.Info("Successfully posted to AWS Step Function");
_logger.Info(response);
}
else
_logger.Error("Error posting to AWS Step Function");
_logger.Error(response);
}
}
Everytime this post is attempted I get the following error:
System.Net.WebException: The remote name could not be resolved: 'https://xxxxxxxxxx.execute-api.us-east-2.amazonaws.com'
Is there something I am missing in posting to this URI or some type of conversion I need to do? Im kind of at a loss on where to go on this on.

Jersey filter giving server error

I am using jersey filter.
In My code logic in AuthenticationFilter.java, if the authorization header is empty, then return the access denied error message.
First time I am hitting the application through rest client tool using the URL without attaching the header
http://localhost:8080/JerseyDemos2/rest/pocservice
Get the status 401 with error message "you cannot access this resource". This is right.
When i tried to hit second time thorugh rest client tool, and server return the exception message.
I deployed my application in tomcat 7.x both windows and linux
Why it give the error when we hit the second time.
How to resolve this
#Provider
public class AuthenticationFilter implements javax.ws.rs.container.ContainerRequestFilter {
#Context
private ResourceInfo resourceInfo;
private static final String AUTHORIZATION_PROPERTY = "Authorization";
private static final Response ACCESS_DENIED = Response.status(Response.Status.UNAUTHORIZED).entity("You cannot access this resource").build();
#Override
public void filter(ContainerRequestContext requestContext) {
// Get request headers
final MultivaluedMap<String, String> headers = requestContext.getHeaders();
// Fetch authorization header
final List<String> authorization = headers.get(AUTHORIZATION_PROPERTY);
// If no authorization information present; block access
if (authorization == null || authorization.isEmpty()) {
requestContext.abortWith(ACCESS_DENIED);
return;
}
}
} }
Error message:
Dec 19, 2016 6:26:18 PM org.glassfish.jersey.server.ServerRuntime$Responder writeResponse
SEVERE: An I/O error has occurred while writing a response message entity to the container output stream.
java.lang.IllegalStateException: The output stream has already been closed.
at org.glassfish.jersey.message.internal.CommittingOutputStream.setStreamProvider(CommittingOutputStream.java:147)
at org.glassfish.jersey.message.internal.OutboundMessageContext.setStreamProvider(OutboundMessageContext.java:803)
......
Please help me
Thanks in advance.
I Removed static variable
private static final Response ACCESS_DENIED = Response.status(Response.Status.UNAUTHORIZED).entity("You cannot access this resource").build();
and i declared local variable. now its working fine.
#Provider
public class AuthenticationFilter implements javax.ws.rs.container.ContainerRequestFilter {
#Context
private ResourceInfo resourceInfo;
private static final String AUTHORIZATION_PROPERTY = "Authorization";
#Override
public void filter(ContainerRequestContext requestContext) {
Response ACCESS_DENIED = Response.status(Response.Status.UNAUTHORIZED).entity("You cannot access this resource").build();
// Get request headers
final MultivaluedMap<String, String> headers = requestContext.getHeaders();
// Fetch authorization header
final List<String> authorization = headers.get(AUTHORIZATION_PROPERTY);
// If no authorization information present; block access
if (authorization == null || authorization.isEmpty()) {
requestContext.abortWith(ACCESS_DENIED);
return;
}
}
} }
You're trying to write in a response that was written before. The full log shows where is it happening. Upload the log and the code where the httpresponse is used/modified.

AWS S3 credential/certificate error

Im totally new to AWS. Im trying to use the AWS S3 notification API's. Im receiving the following error.
com.amazonaws.services.sns.model.AmazonSNSException: The security token included in the request is invalid. (Service: AmazonSNS; Status Code: 403; Error Code: InvalidClientTokenId; ...
I have NO idea what's wrong. For my accessID and secretID. Im using the main AWS codes for authentication. Am I supposed to use the main AWS credentials, or something else. Im not using any type of certificate. I dont know if they are even required.
Im using the example code supplied by AWS with some modifications to read a property file instead of hard coding the accessID and secretID.
Can someone please steer me in the right direction? I am completely confused.
public class AmazonSNSReceiver {
// AWS credentials -- replace with your credentials
static String ACCESS_KEY;
static String SECRET_KEY;
// Shared queue for notifications from HTTP server
static BlockingQueue<Map<String, String>> messageQueue = new LinkedBlockingQueue<Map<String, String>>();
// Receiver loop
public static void main(String[] args) throws Exception {
AmazonSNSReceiver sns = new AmazonSNSReceiver();
sns.getPropertyValues();
if (args.length == 1) {
sns.SNSClient(args[0]);
} else {
sns.SNSClient("8989");
}
}
// Create a client
public void SNSClient(String thisport) throws Exception{
AmazonSNSClient service = new AmazonSNSClient(new BasicAWSCredentials(ACCESS_KEY, SECRET_KEY));
// Create a topic
CreateTopicRequest createReq = new CreateTopicRequest().withName("MyTopic");
CreateTopicResult createRes = service.createTopic(createReq);
// Get an HTTP Port
int port = thisport == null ? 8989 : Integer.parseInt(thisport);
// Create and start HTTP server
Server server = new Server(port);
server.setHandler(new AmazonSNSHandler());
server.start();
// Subscribe to topic
SubscribeRequest subscribeReq = new SubscribeRequest()
.withTopicArn(createRes.getTopicArn())
.withProtocol("http")
.withEndpoint("http://" + InetAddress.getLocalHost().getHostAddress() + ":" + port);
service.subscribe(subscribeReq);
for (;;) {
// Wait for a message from HTTP server
Map<String, String> messageMap = messageQueue.take();
// Look for a subscription confirmation Token
String token = messageMap.get("Token");
if (token != null) {
// Confirm subscription
ConfirmSubscriptionRequest confirmReq = new ConfirmSubscriptionRequest()
.withTopicArn(createRes.getTopicArn())
.withToken(token);
service.confirmSubscription(confirmReq);
continue;
}
// Check for a notification
String message = messageMap.get("Message");
if (message != null) {
System.out.println("Received message: " + message);
}
}
}
public void getPropertyValues() throws IOException {
Properties prop = new Properties();
InputStream properties = getClass().getClassLoader().getResourceAsStream("SNS.properties");
prop.load(properties);
ACCESS_KEY = prop.getProperty("ACCESS_KEY");
SECRET_KEY = prop.getProperty("SECRET_KEY");
}
// HTTP handler
static class AmazonSNSHandler extends AbstractHandler {
// Handle HTTP request
public void handle(String target, HttpServletRequest request, HttpServletResponse response, int dispatch) throws IOException {
// Scan request into a string
Scanner scanner = new Scanner(request.getInputStream());
StringBuilder sb = new StringBuilder();
while (scanner.hasNextLine()) {
sb.append(scanner.nextLine());
}
// Build a message map from the JSON encoded message
InputStream bytes = new ByteArrayInputStream(sb.toString().getBytes());
Map<String, String> messageMap = new ObjectMapper().readValue(bytes, Map.class);
// Enqueue message map for receive loop
messageQueue.add(messageMap);
// Set HTTP response
response.setContentType("text/html");
response.setStatus(HttpServletResponse.SC_OK);
((Request) request).setHandled(true);
}
}
}
Your application needs to provide AWS credentials. These credentials can be obtained by several methods:
Create an IAM User and generate an Access Key and Secret Key. Include the credentials in a configuration file (it is not a good idea to put them in your application, since they could accidentally be published elsewhere).
If running the code on an Amazon EC2 instance, create an IAM Role and assign the role to the instance when it is launched. Credentials will then be automatically provided to applications running on that instance.
It is also necessary to assign permissions to the IAM User/Role. These permissions grant the right to call various AWS API calls. The fact that you receive an AuthorizationError suggests that the credentials in use do not have sufficient permissions.
See: Managing Access to Your Amazon SNS Topics