I've just started to work with Amazon S3 in my ASP.NET project. I can upload images, delete them, and show on browser. But when I was trying to get image-object from code-behind by a simple GetObjectRequest to load it to a simple stream, I've got an exeption "Access denied: The remote server returned an error: (403) Forbidden.". And it's very strange 'cause i can delete an object but have no access to get it?
Here is my Get Request code:
using (var client = new AmazonS3Client(Amazon.RegionEndpoint.EUWest1))
{
GetObjectRequest request = new GetObjectRequest
{
BucketName = bucketName,
Key = keyName
};
GetObjectResponse response = client.GetObject(request);
return response.ResponseStream;
}
Which doesn't work.
And this DELETE request works correct
DeleteObjectRequest deleteObjectRequest = new DeleteObjectRequest
{
BucketName = bucketName,
Key = keyName
};
client.DeleteObject(deleteObjectRequest);
I think that it could be a problem with my bucket policy, but i don't understand what exactly
{
"Version": "2008-10-17",
"Id": "Policy1437483839592",
"Statement": [
{
"Sid": "Stmt1437483828676",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::ama.dyndns.tv/*",
"Condition": {
"StringLike": {
"aws:Referer": [
"MyIP",
"MyTeammateIP"
]
}
}
},
{
"Sid": "Givenotaccessifrefererisnomysites",
"Effect": "Deny",
"Principal": {
"AWS": "*"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::ama.dyndns.tv/*",
"Condition": {
"StringNotLike": {
"aws:Referer": [
"MyIP",
"MyTeammateIP"
]
}
}
}
]
}
Your first bucket policy statement allows a GET request when the Referer: http request leader's value is present and matches one of the supplied values. (Note that this is is a very primitive access control mechanism, as the header is easily forged).
The second policy denies requests where the referer doesn't match any value from the supplied list.
The referer is nothing more than a request header sent by the browser or http user agent library. When you are sending your GET request from code, there's not going to be a referer header present, unless you forge one yourself, as part of the request. Any matching Deny policy overrides not only any matching Allow policy... it also overrides any authentication credentials you supply. Hence, the problem.
If you don't set the acl on the object to something that allows public access (such as x-amz-acl: public-read) then the Deny policy is unnecessary. The object will not be downloadable in that case, because the deny is implicit unless the Allow policy is matched or you provide valid authentication credentials. Everything is denied by default in S3 unless you allow it via the object permissions/acl, bucket policy, or IAM user policy, and even if you do, a matching explicit Deny always prevails.
If the object does not exist and the executing code does not have ListBucket permission, then a 403 will be returned even if the calling code has getObject permissions.
Take a look at the permissions section: http://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectGET.html
Related
I am currently a CORS issue in my NextJs App. When I run the app on let's say on localhost:3030, and I make an API call to http://some-api.com, I get the following error:
Access to XMLHttpRequest at 'http://some-api.com' from origin 'http://localhost:3030' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: The 'Access-Control-Allow-Origin' header has a value 'http://localhost:3000' that is not equal to the supplied origin.
I added the following lines to the next.config.js.
process.env.NEXT_PUBLIC_SOME_HOST=http://some-api.com
async rewrites() {
return [
{
source: '/api/:path*',
destination: process.env.NEXT_PUBLIC_SOME_HOST + '/:path*'
}
]
},
//avoiding CORS error, more here: https://vercel.com/support/articles/how-to-enable-cors
async headers() {
return [
{
// matching all API routes
source: "/api/:path*",
headers: [
{ key: "Access-Control-Allow-Credentials", value: "true" },
{ key: "Access-Control-Allow-Origin", value: process.env.NEXT_PUBLIC_SOME_HOST},
{ key: "Access-Control-Allow-Methods", value: "GET,OPTIONS,PATCH,DELETE,POST,PUT" },
{ key: "Access-Control-Allow-Headers", value: "X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version" },
]
}
]
},
But it still does not work.
I also attached of the response header on the OPTIONS call.
I can see that the access-control-allow-origin is set to http:localhost:3000 I think if I override that value to localhost:3030 it would work but I am not sure how to do that.
I am pretty new to NextJs, so some help would be greatly appreciated.
Updating the CorsFilter on the Back end API to allow response to http://localhost:3030 solved the problem.
My back end API is written in Spring Boot.
So I added the following:
httpServletResponse.setHeader("Access-Control-Allow-Origin", "http://localhost:3030");
Note: It also possible to allow all with "*"
I'm going to be mirroring my Cloud Storage bucket to another Object Store, and want to only make publicly accessible objects that Cloud Storage would allow any unauthenticated user to read.
I'd like to, when given an object path to an object in Cloud Storage, determine if the object is publicly accessible (the check would be happening in a server context that has access to firebase admin).
What are the options here? Is there some way to run a test request through existing rules? Or would I need to GET (or HEAD?) the object using fetch w/o auth to determine if it's accessible? I could access the rules directly and manually parse them, but that feels really fragile.
Maybe storing some info in metadata where I tag the level of access unauthenticated users should have, and tie that into the metadata rules one can write for cloud storage?
Anyhow, curious if there is an existing pattern for this. Thanks in advance!
I believe you are interested in the projects.test method from the REST API. You would construct a test case with an expectation of ALLOW. Your code may look something like this :
{
"testSuite": {
"testCases": [
{
"expectation": "ALLOW",
"request": {
"path": "/b/myapp.appspot.com/o/folder/obj_id",
"method": "get",
"auth": null,
"time": "2022-11-30T23:30:08.199Z",
"params": {}
},
"functionMocks": [],
"pathEncoding": "PLAIN",
"expressionReportLevel": "VISITED"
}
]
},
"source": {
"files": [
{
"name": "simulator.rules",
"content": "rules_version = '2';\nservice firebase.storage {\n match /b/{bucket}/o {\n match /{allPaths=**} {\n allow read, write: if\n request.time < timestamp.date(2022, 12, 30);\n }\n }\n}"
}
]
}
}
The test results would then contain an array of results with a state containing whether or not the test succeeded or failed:
On Success
{
"testResults": [
{
"state": "SUCCESS",
...
On Failure
{
"testResults": [
{
"state": "FAILURE",
...
I would just use the admin sdk to lookup your security rules for the source JSON file beforehand or I would cache it and update it in your function.
I'm using GithubAuthProvider with the added scope repo to get the user's access token which is later used to access the GitHub GraphQL API (the GitHub App has the permissions for Contents and Metadata set to Read-only).
The problem is when I'm trying to list private repos. The API returns an empty array as if I don't have the required permissions. Moreover, when I try to list branches of a user's repo it returns an error of type FORBIDDEN.
Query:
query {
viewer {
repository(name: "some-repo") {
refs(refPrefix: "refs/heads/", first: 10) {
nodes {
name
}
}
}
}
}
Response:
{
"data": {
"viewer": {
"repository": {
"refs": null
}
}
},
"errors": [
{
"type": "FORBIDDEN",
"path": [
"viewer",
"repository",
"refs"
],
"extensions": {
"saml_failure": false
},
"locations": [
{
"line": 7,
"column": 7
}
],
"message": "Resource not accessible by integration"
}
]
}
What am I missing?
For GitHub GraphQL API, only scope repo may not be enough.
Following are scopes requested for reference. Authenticating with GraphQL
user
public_repo
repo
repo_deployment
repo:status
read:repo_hook
read:org
read:public_key
read:gpg_key
The API returns an empty array as if I don't have the required permissions.
I wonder whether you are query under the viewer. viewer can get the private repos he/she owned. For repos owned by other people, you can try
repository(name: "repo-name", owner: "login") {
name
}
It will return NOT_FOUND error if you don't have the required permissions.
Your query works fine for me :)
It turns out I read through the Firebase instructions too fast and created a Github App instead of an OAuth App.
It's now working as it should.
I've been loosely following the boilerplate in quickstart-js. I don't want to rely on Chrome's identify provider but rather want users to be able to sign in to my extension with their Google login using a popup so I haven't gone through the song and dance of requesting identity permissions in my manifest.json. My file is as follows:
{
"manifest_version": 2,
"name": "Firebase Auth in Chrome Extension Sample",
"description": "This sample shows how to authorize Firebase in a Chrome extension using a Google account.",
"version": "2.1",
"icons": {
"128": "firebase.png"
},
"browser_action": {
"default_icon": "firebase.png",
"default_popup": "credentials.html"
},
"background": {
"page": "background.html"
},
"content_security_policy":"script-src 'self' https://apis.google.com https://www.gstatic.com/ https://*.firebaseio.com https://www.googleapis.com; object-src 'self'"
}
I have baseline code that is similar to what's in quickstart-js. The relevant portion in my credentials.js is here:
/**
* Start the auth flow and authorizes to Firebase.
*/
async function startAuth() {
await firebase.auth().setPersistence(firebase.auth.Auth.Persistence.SESSION);
const provider = new firebase.auth.GoogleAuthProvider();
const res = await firebase.auth().signInWithPopup(provider);
}
// Starts the sign-in process.
function startSignIn() {
document.getElementById('quickstart-button').disabled = true;
if (firebase.auth().currentUser) {
firebase.auth().signOut();
} else {
startAuth();
}
}
window.onload = function() {
initApp();
};
This seems like it should work but constantly receive the following message:
Uncaught (in promise) Error: This chrome extension ID (chrome-extension://cckmbfklaloiadcphibealkhpncehpng) is not authorized to run this operation. Add it to the OAuth redirect domains list in the Firebase console -> Auth section -> Sign in method tab.
According to the official docs, I should be able to whitelist my Chrome extension's ID in the Firebase control panel. I'm repeatedly given a success message but the extension "url" doesn't show up in my list of Authorized Domains and I keep getting the error message.
Is there somewhere else I need to add the Chrome Extension url?
This seems to have just been a regression. I reached out to Firebase support, got an answer a few days later, but by that point the bug was fixed.
I'm referring to use Openstack API to get quota usage from Openstack Cloud. I did exactly as document at https://developer.openstack.org/api-ref/compute/.
But It didn't work, with api:
<host>/v2/{tenant_id}/os-quota-sets/{tenant_id}/detail
or
<host>/v2/{tenant_id}/os-quota-sets/detail
It worked with api:
<host>/v2/{tenant_id}/os-quota-sets/{tenant_id}
But, I want to get details. Did I do anything wrong?
OpenStack client can be used... And you can use command line tools.... Below is the link which can help you.
https://docs.openstack.org/nova/pike/admin/quotas.html
You can install OpenStack SDK, you can go through API documentation section for networking.
Below is the link:
https://docs.openstack.org/openstacksdk/latest/user/proxies/network.html#openstack.network.v2._proxy.Proxy.update_quota
You may find methods like:
delete_quota(quota, ignore_missing=True)
get_quota(quota, details=False)
API for getting project quota can be called as,
requests.get('http://'+url+':8774/v2.1/os-quota-sets/'+projectid+'/detail',headers={'content-type': 'application/json', 'X-Auth-Token': token})
You will have to pass your project id in path and 'X-Auth-Token' parameter in headers which can be extracted as,
url = [Your Cloud Machine IP Goes here]
def gettokenForUser(username,password):
payload1 = {
"auth": {
"identity": {
"methods": [
"password"
],
"password": {
"user": {
"name": username,
"domain": {
"name": "Default"
},
"password": password
}
}
}
}
}
response = requests.post('http://'+url+':5000/v3/auth/tokens',
headers={'content-type': 'application/json'},
data=json.dumps(payload1))
return response.headers['X-Subject-Token']