I've set my AWS Elasticsearch instance so that anyone can do anything (create, delete, search, etc.) to it.
These are my permissions (replace $myARN with my Elasticsearch ARN):
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "es:*",
"Resource": "$myARN"
}
]
}
When I PUT a new index:
PUT http://my-elasticsearch-domain.us-west-2.es.amazonaws.com/index-name
Or I DELETE an index:
DELETE http://my-elasticsearch-domain.us-west-2.es.amazonaws.com/index-name
I get this:
{
"acknowledged": true
}
Which means I can create and delete indexes but when I try to POST a reindex I get:
{
"Message": "Your request: '/_reindex' is not allowed."
}
Do I have to sign this request? Why should I have to sign this request but not creating or deleting indexes?
The reason is simply because the Amazon Elasticsearch Service is a kind of restricted environment where you don't have access to the full range of services and endpoints provided by a barebone install of Elasticsearch.
You can check the list of endpoints that you're allowed to use on the Amazon Elasticsearch Service and _reindex is not part of that list.
UPDATE
There's another way to achieve what you want, though. By leveraging Logstash, you can source the data from ES, apply any transformation you wish and sink it back to ES.
input {
elasticsearch {
hosts => ["my-elasticsearch-domain.us-west-2.es.amazonaws.com:80"]
index => "index-name"
docinfo => true
}
}
filter {
mutate {
remove_field => [ "#version", "#timestamp" ]
}
# add other transformations here
}
output {
elasticsearch {
hosts => ["my-elasticsearch-domain.us-west-2.es.amazonaws.com:80"]
manage_template => false
index => "%{[#metadata][_index]}"
document_type => "%{[#metadata][_type]}"
document_id => "%{[#metadata][_id]}"
}
}
Reindex feature will not be available in previous versions 1.5 and 2.3. So currently if you use the versions 1.5 or 2.3, it would be good for you to move on to the latest ES version so that you will get better indexing performance and other features which are not supported in previous versions.
Also have a look into the below link to know more the APIs which are supported in different versions of AWS Elasticsearch. If you look into the 5.1 section you can the “_reindex” is listed there.
http://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/aes-supported-es-operations.html#es_version_5_1
I was able to do this using the following tool
taskrabbit/elasticsearch-dump
After installing it, you can run this on the command line:
elasticdump \
--input=http://es.com:9200/api/search \
--input-index=my_index \
--output=http://es.com:9200/api/search \
--output-index=my_index \
--type=mapping
NOTE: I did have to use the --awsChain option to find my credentials.
Related
I'm trying to create users and roles via the elasticsearch python client documented here: https://elasticsearch-py.readthedocs.io/en/v7.14.1/. If I use HTTP requests alone and if I ignore the certificates, I can reach the application and make requests with the payloads suggested in https://opendistro.github.io/for-elasticsearch-docs/docs/security/access-control/api/. However I'm trying to use a secure connection to get to elasticsearch in AWS. According to their documentation in https://docs.aws.amazon.com/opensearch-service/latest/developerguide/request-signing.html#request-signing-python, I should be using the elastic search client like this:
region = 'my-region-1'
service = 'opensearchservice'
credentials = boto3.Session().get_credentials()
awsauth = AWS4Auth(credentials.access_key, credentials.secret_key, region, service,
session_token=credentials.token)
elasticsearch = Elasticsearch(
hosts=[{'host': self._host, 'port': 443}],
http_auth=awsauth,
use_ssl=True,
verify_certs=True,
connection_class=RequestsHttpConnection
)
I'm using boto3 to create the session and AWS4Auth to try and get the secure connection. However, I can't find anywhere how to actually send a plain payload to elastic search endpoints. For example, for this endpoint:
curl -X PUT http://localhost:443/_opendistro/_security/api/roles/jesperancinha-role -d "{}" (...)
It seems like that we need to send an index and that's not what I'm looking for. I just want to create a user with a payload like this one:
{
"cluster_permissions" : [
"indices_monitor",
],
"index_permissions" : [
{
"index_patterns" : [
"*"
],
"dls" : "",
"fls" : [ ],
"masked_fields" : [ ],
"allowed_actions" : [
"read",
"indices:monitor/stats"
]
}
],
"tenant_permissions" : [
{
"tenant_patterns" : [
"human_resources"
],
"allowed_actions" : [
"kibana_all_read"
]
}
]
}
It would be great if this could be done via the elasticsearch-py client, but if you have any other idea, please let me know. Thanks!
I hope I didn't get people too confused with my question. I finally found out what I wanted. The elasticsearch client does work, but only for searches and indexing. For administrator tasks, I found out that I need to make normal requests as described in the open distro for elastic search, except that they also need to be signed with Signature Version 4. The whole thing is pretty complicated but very nicely layed out in the AWS website: https://docs.aws.amazon.com/general/latest/gr/sigv4-signed-request-examples.html.
We are using WSO2 SCIM apis to define roles to user and update it.
For role update operation , we are currently adding the new user role(add user to new role group using SCIM api) , and then delete the existing user role (call users SCIM GET request under a GROUP, delete the existing user from the list and use the newly created list as body arguments to call SCIM PATCH request for the GROUP). With this approach , we were able to update roles. But as the user base increased , the above approach of PATCH operation is getting timeout error .(The new role gets updated to user, but the existing role persists as the 2nd api is getting failed).
Below is one solution which i tried out :
Add new role, delete the newly created role inside user details and call PATCH api with the updated roles of user. But then realized on further investigation that roles inside user is readonly and can't be updated using patch/put operations. So i failed in getting a proper solution .
Is there a way to update a single user's role inside the GROUP without using PATCH /Groups endpoint ?
As I have mentioned in the answer https://stackoverflow.com/a/64225419/10055162, the SCIM specification doesn't allow to update the user's group attribute using PATCH /Users/{userId}.
Also, PATCH /Groups/{groupId} may cause performance issues when the group's member count is too high.
WSO2 IS has improved the performance of PATCH /Groups/{groupId} to some extent.
https://github.com/wso2/product-is/issues/6918 - available 5.10.0 onwards
https://github.com/wso2/product-is/issues/9120 - available 5.11.0 onwards
So, if you are using an older version of IS, can you please try with the latest GA release(5.11.0). It may improve the performance.
UPDATED:
You can use SCIM POST /Bulk endpoint to update user's groups by single REST call, instead of having multiple PATCH /Groups/{group-id} calls.
Refer to https://anuradha-15.medium.com/scim-2-0-bulk-operation-support-in-wso2-identity-server-5-10-0-8041577a4fe3 for more details on Bulk endpoint.
example:
To assign two groups (Group1 and Group2) to a user, execute POST https://<host>:<port>/scim2/Bulk with payload similar to the following.
{
"Operations": [
{
"data": {
"Operations": [
{
"op": "add",
"value": {
"members": [
{
"display": "anuradha",
"value": "db15b161-a205-454d-9da1-4a2a0df0585e"
}
]
}
}
]
},
"method": "PATCH",
"path": "/Groups/f707b6cc-91f8-4b8a-97fb-a01c2a79515c"
},
{
"data": {
"Operations": [
{
"op": "add",
"value": {
"members": [
{
"display": "anuradha",
"value": "db15b161-a205-454d-9da1-4a2a0df0585e"
}
]
}
}
]
},
"method": "PATCH",
"path": "/Groups/8c91215f-1b7a-4cdb-87d9-ae29c60d70de"
}
],
"schemas": [
"urn:ietf:params:scim:api:messages:2.0:BulkRequest"
]
}
I am trying to deploy my nuxt static website to S3 using this guide.
https://nuxtjs.org/faq/deployment-aws-s3-cloudfront
The deployscript works when using which I tried an a personal AWS account:
AWS_ACCESS_KEY_ID="key"
AWS_SECRET_ACCESS_KEY="secret"
It does not work when unsetting these exports and using the AWS_PROFILE export on a separate AWS account. On this AWS I am not able to get an access key and secret because of company policy.
I also use these AWS profiles for other things so I am sure they are configured properly.
The error I am getting in the console is:
Error: Connect EHOSTUNREACH <EC2 IP address???>
The part in brackets is the IP address I am seeing. Which is weird where it tries to connect to EC2 since the script works on S2 and cloudfront.
The script I am using
#!/bin/bash
export AWS_PROFILE="profile_name"
export AWS_BUCKET_NAME="example.com"
export AWS_CLOUDFRONT="UPPERCASE"
# Load nvm (node version manager), install node (version in .nvmrc), and npm install packages
[ -s "$HOME/.nvm/nvm.sh" ] && source "$HOME/.nvm/nvm.sh" && nvm use
# Npm install if not already.
[ ! -d "node_modules" ] && npm install
npm run generate
gulp deploy
As for the gulpfile:
const gulp = require('gulp')
const awspublish = require('gulp-awspublish')
const cloudfront = require('gulp-cloudfront-invalidate-aws-publish')
const parallelize = require('concurrent-transform')
// https://docs.aws.amazon.com/cli/latest/userguide/cli-environment.html
const config = {
// Required
params: {
Bucket: process.env.AWS_BUCKET_NAME
},
credentials: {
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
signatureVersion: 'v3'
},
// Optional
deleteOldVersions: false, // NOT FOR PRODUCTION
distribution: process.env.AWS_CLOUDFRONT, // CloudFront distribution ID
region: process.env.AWS_DEFAULT_REGION,
headers: {
/* 'Cache-Control': 'max-age=315360000, no-transform, public', */
},
// Sensible Defaults - gitignore these Files and Dirs
distDir: 'dist',
indexRootPath: true,
cacheFileName: '.awspublish',
concurrentUploads: 10,
wait: true // wait for CloudFront invalidation to complete (about 30-60 seconds)
}
gulp.task('deploy', function () {
// create a new publisher using S3 options
// http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#constructor-property
const publisher = awspublish.create(config)
let g = gulp.src('./' + config.distDir + '/**')
// publisher will add Content-Length, Content-Type and headers specified above
// If not specified it will set x-amz-acl to public-read by default
g = g.pipe(
parallelize(publisher.publish(config.headers), config.concurrentUploads)
)
// Invalidate CDN
if (config.distribution) {
console.log('Configured with CloudFront distribution')
g = g.pipe(cloudfront(config))
} else {
console.log(
'No CloudFront distribution configured - skipping CDN invalidation'
)
}
// Delete removed files
if (config.deleteOldVersions) {
g = g.pipe(publisher.sync())
}
// create a cache file to speed up consecutive uploads
g = g.pipe(publisher.cache())
// print upload updates to console
g = g.pipe(awspublish.reporter())
return g
})
The gulp-awspublish docs mention it should be possible to connect with an AWS profile by adding it to the export (which I do in my deploy file).
They also mention using the aws js sdk which I also tried by integrating following snippet.
var AWS = require("aws-sdk");
var publisher = awspublish.create({
region: "your-region-id",
params: {
Bucket: "..."
},
credentials: new AWS.SharedIniFileCredentials({ profile: "myprofile" })
});
When I use the export aws_profile it does at least seam to authenticate. When using the SDK I receive an error mentioning
CredentialsError: Missing Credentials in config, if using
AWS_CONFIG_FILE, set AWS_SDK_LOAD_CONFIG=1
Where adding the latter (AWS_SDK_LOAD_CONFIG=1) to my deployment script does not make any difference.
Any Idea if I a missing something in the script to make it work?
My user policies where set as mentioned in the tutorial. Maybe they forgot something?
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["s3:ListBucket"],
"Resource": ["arn:aws:s3:::example.com"]
},
{
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:PutObjectAcl",
"s3:GetObject",
"s3:GetObjectAcl",
"s3:DeleteObject",
"s3:ListMultipartUploadParts",
"s3:AbortMultipartUpload"
],
"Resource": ["arn:aws:s3:::example.com/*"]
},
{
"Effect": "Allow",
"Action": [
"cloudfront:CreateInvalidation",
"cloudfront:GetInvalidation",
"cloudfront:ListInvalidations",
"cloudfront:UnknownOperation"
],
"Resource": "*"
}
]
}
Since awspublish uses the javascript sdk I needed to export AWS_SDK_LOAD_CONFIG=true which solved the issue!
I'm getting GraphQLError: Request failed with status code 401
I followed the automatic configuration instructions from:
https://aws.github.io/aws-amplify/media/api_guide#automated-configuration-with-cli
I tried looking, but there are a lack of resources for IAM. It looks like everything should be setup automatically, and done with the Amplify CLI after I put in the IAM access key and secret.
Is further setup required? Here is my code:
import Amplify, { API, graphqlOperation, Hub } from "aws-amplify";
import aws_config from "../../aws-exports";
Amplify.configure(aws_config);
const ListKeywords = `query ListKeywords {
listKeyword {
keyword {
id
name
}
}
}`;
const loop = async () => {
const allKeywords = await API.graphql(graphqlOperation(ListKeywords));
}
Could it also be because my GraphQL resolvers are not setup yet for ListKeywords?
If you're using IAM as the Authorization type on your AppSync API then the issue is the Cognito Role being used with the Auth category when invoking Amplify.configure() isn't granted permissions for GraphQL operations. It needs something like this attached:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"appsync:GraphQL"
],
"Resource": [
"arn:aws:appsync:us-west-2:123456789012:apis/YourGraphQLApiId/*"
]
}
]
}
More details here: https://docs.aws.amazon.com/appsync/latest/devguide/security.html
Not sure if this helps but I've been struggling with this for a while and found that if I add the API and use IAM as the auth method I need to add 'auth' to the schema too.
See below:
type TimeLapseCamera #model
#auth(rules: [
{ allow: private, provider: iam }
])
{
...
}
I just tested this and my web page is successfully adding a record.
Note to other comment; I do not have AWS at all in this - its a simple VUE app with Amplify.
I just changed ~/.aws/credentials and now it's working.
Looks like even if you have project specific configuration via Amplify's command line tools or ~/.awsmobile/aws-config.js, it still relies on ~/.aws
The command I use:
aws s3api put-bucket-notification-configuration --bucket bucket-name --notification-configuration file:///Users/chris/event_config.json
Works fine if I take out the "Filter" key. As soon as I add it in, I get:
Parameter validation failed:
Unknown parameter in NotificationConfiguration.LambdaFunctionConfigurations[0]: "Filter", must be one of: Id, LambdaFunctionArn, Events
Here's my JSON file:
{
"LambdaFunctionConfigurations": [
{
"LambdaFunctionArn": "arn:aws:lambda:us-east-1:000000000:function:name",
"Events": [
"s3:ObjectCreated:*"
],
"Filter": {
"Key": {
"FilterRules": [
{
"Name": "prefix",
"Value": "images/"
}
]
}
}
}
]
}
When I look at the command's docs (http://docs.aws.amazon.com/cli/latest/reference/s3api/put-bucket-notification-configuration.html), I don't see any mistake. I've tried copy/pasting, carefully looking over, etc... Any help would be greatly appreciated!
You need to be running at least version 1.7.46 of aws-cli, released 2015-08-20.
This release adds Amazon S3 support for event notification filters and fixes some issues.
https://aws.amazon.com/releasenotes/CLI/3585202016507998
The aws-cli utility contains a lot of built-in intelligence and validation logic. New features often require the code in aws-cli to be updated, and Filter on S3 event notifications is a relatively recent feature.
See also: https://aws.amazon.com/blogs/aws/amazon-s3-update-delete-notifications-better-filters-bucket-metrics/