I used environment variables before and it worked fine.
Now I am migrating my config variables into a single file and I have AWS_SECRET_ACCESS_KEY and AWS_ACCESS_KEY_ID variables containing respective values that are loaded from this file.
I tried this code but receiving an error:
creds := credentials.NewStaticCredentials("123", conf.AWS_SECRET_ACCESS_KEY, conf.AWS_ACCESS_KEY_ID)
sess, err := session.NewSession(&aws.Config{Credentials: creds})
Here is the error
InvalidClientTokenId: The security token included in the request is invalid.
How do I properly inject my keys into the aws sdk calls?
Try re-ordering your args so that ACCESS_KEY is the 1st param and SECRET_KEY is the second:
creds := credentials.NewStaticCredentials(conf.AWS_ACCESS_KEY_ID, conf.AWS_SECRET_ACCESS_KEY, "")
Try adding the region as well:
sess, err := session.NewSession(&aws.Config{
Region: aws.String("us-west-2"),
Credentials: credentials.NewStaticCredentials(conf.AWS_ACCESS_KEY_ID, conf.AWS_SECRET_ACCESS_KEY, ""),
})
Or you can just temporaly set Environment variables.
package main
import (
"fmt"
"os"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/s3/s3manager"
)
const (
AccessKeyId = "XXXXXXXXXXXXXXXXXX"
SecretAccessKey = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
Region = "eu-west-1"
Bucket = "XXXXX-XXXX-XXX"
)
func main() {
os.Setenv("AWS_ACCESS_KEY_ID", AccessKeyId)
os.Setenv("AWS_SECRET_ACCESS_KEY", SecretAccessKey)
filename := os.Args[1]
file, err := os.Open(filename)
if err != nil {
fmt.Println("Failed to open file", filename, err)
os.Exit(1)
}
defer file.Close()
conf := aws.Config{Region: aws.String(Region)}
sess := session.New(&conf)
svc := s3manager.NewUploader(sess)
fmt.Println("Uploading file to S3...")
result, err := svc.Upload(&s3manager.UploadInput{
Bucket: aws.String(Bucket),
Key: aws.String(filepath.Base(filename)),
Body: file,
})
if err != nil {
fmt.Println("error", err)
os.Exit(1)
}
}
Additionally, if you hadn't known, the SDK allows for the use of the shared config under .aws/config. You can put your values in there and then set the environment variable AWS_SDK_LOAD_CONFIG to a truthy value to load the shared config. An example shared config would look like this:
[default]
aws_access_key_id = AKID
aws_secret_access_key = SECRET
Then running:
AWS_SDK_LOAD_CONFIG=true go run main.go
Connect your sdk client using this generic service
var awsSession *session.Session
func init() {
initializeAwsSession()
}
func initializeAwsSession() {
awsSession = session.Must(session.NewSession(&aws.Config{
Region: aws.String("ap-southeast-1"),
Credentials: credentials.NewStaticCredentials("YOUR_ACCESS_KEY","YOUR SECRET_KEY", ""),
}))
}
Related
I am using Amazon Kinesis and the Go SDK for AWS, but I'm getting an error.
This is my code:
package main
import (
"math/rand"
"strings"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
_kinesis "github.com/aws/aws-sdk-go/service/kinesis"
)
func main() {
session, err := session.NewSession(&aws.Config{
Region: aws.String("us-east-1"),
})
handleErr(err)
kinesis := _kinesis.New(session)
laugh := strings.Builder{}
laughingSounds := []string{"haha", "hoho", "hehe", "hehehe", "*snicker*"}
for i := 0; i < 10; i++ {
laugh.WriteString(laughingSounds[rand.Intn(len(laughingSounds))])
}
_, err = kinesis.PutRecord(&_kinesis.PutRecordInput{
Data: []byte(laugh.String()),
PartitionKey: aws.String("laughs"),
StreamName: aws.String("laughs"),
})
handleErr(err)
}
func handleErr(err error) {
if err != nil {
panic(err)
}
}
When I run this, I get an error:
panic: UnrecognizedClientException: The security token included in the request is invalid.
status code: 400, request id: dc139793-cd38-fb30-86a3-f92b6410e1c7
goroutine 1 [running]:
main.handleErr(...)
C:/Users/####/----/main.go:5
main.main()
C:/Users/####/----/main.go:34 +0x3ac
exit status 2
I have run aws configure:
$ aws configure
AWS Access Key ID [None]: ####
AWS Secret Access Key [None]: ####
Default region name [None]: us-east-1
Default output format [None]:
and the C:/users/####/.aws/credentials file is created with the correct configuration. But my program still wouldn't execute successfully.
I tried to set an environment variable, but to no avail.
$ $env:aws_access_key_id="####"
Version info:
$ pwsh -v
PowerShell 7.2.2
$ aws -v
aws-cli/2.4.27 Python/3.8.8 Windows/10 exe/AMD64 prompt/off
OS: Windows 11
I found the answer in GoDoc, I just had to change a config setting and use NewSessionWithOptions:
session, err := session.NewSessionWithOptions(session.Options{
Config: aws.Config{
Region: aws.String("<your region>"),
}, SharedConfigState: session.SharedConfigEnable,
})
Be sure to run aws configure with the correct credentials (or even just manually create the ~/.aws/credentials file), or this won't work.
I am trying to create Amazon SQS from my local machine and facing errors like
Got an error while trying to create queue: NoCredentialProviders: no valid providers in chain. Deprecated.
For verbose messaging see aws.Config.CredentialsChainVerboseErrors
What I did:
Step-1:
I have set up my credentials in .aws/credentials file
[default]
aws_access_key_id = TestAccessKey
aws_secret_access_key = TestSecretAccessKey
Step-2:
My code in go lang like below
package main
import (
"fmt"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/sqs"
)
func CreateQueue(sess *session.Session, queueName string) (*sqs.CreateQueueOutput, error) {
sqsClient := sqs.New(sess)
result, err := sqsClient.CreateQueue(&sqs.CreateQueueInput{
QueueName: &queueName,
Attributes: map[string]*string{
"DelaySeconds": aws.String("0"),
"VisibilityTimeout": aws.String("60"),
},
})
if err != nil {
return nil, err
}
return result, nil
}
func main() {
sess, err := session.NewSessionWithOptions(session.Options{
Profile: "default",
Config: aws.Config{
Region: aws.String("us-east-1"),
},
})
if err != nil {
fmt.Printf("Failed to initialize new session: %v", err)
return
}
queueName := "my-new-queue"
createRes, err := CreateQueue(sess, queueName)
if err != nil {
fmt.Printf("Got an error while trying to create queue: %v", err)
return
}
fmt.Println("Created a new queue with url: " + *createRes.QueueUrl)
}
Step-3:
Try updating profile in Shared Credential File (.aws/credentials) as below:
[default]
aws_access_key_id=TestAccessKey
aws_secret_access_key=TestSecretAccessKey
region=us-east-1
I just added region at the end.
To verify if your CLI session has correct AWS credentials configured run this command aws sts get-caller-identity This command will show which profile is used. If this works fine then you can run any simple AWS commands something like S3.getBuckets() to verify if the dev environment is setup correctly.
These 2 solutions should give you enough input to figure out what's wrong.
Need to download a file from s3 bucket and store in to tmp directory in lambda function. After that need apply grep command into file using "os/exec". I tried to do this algorithm using golang.
I tried through following way but it is not successful approach.
func MyHandler(ctx context.Context, s3Event events.S3Event) {
for _, record := range s3Event.Records {
s3record := record.S3
bucketName := s3record.Bucket.Name
fileName := s3record.Object.Key
download_path := "/tmp/"
file, err := os.Create(download_path + fileName)
if err != nil {
fmt.Println(err)
}
defer file.Close()
sess, _ := session.NewSession(&aws.Config{Region: aws.String("us-east-1")})
downloader := s3manager.NewDownloader(sess)
numBytes, err := downloader.Download(file,
&s3.GetObjectInput{
Bucket: aws.String(bucketName),
Key: aws.String(fileName),
})
if err != nil {
fmt.Println(err)
}
fmt.Println("Downloaded", file.Name(), numBytes, "bytes")
}
}
Please verify may approach correct or suggest a correct approach to store the file from s3 bucket into tem folder of lambda function everything I need to do using golang.
I have following confusion also
Do we need to create directory folder in lambda function or it is a default directory already there.
Can we apply os/exec command into tem folder and can we grep the file.
Do we need to delete uploaded file from tem folder then How? or The file will be deleted a automatically.
I am using AWS S3 service to upload images. Yesterday I updated the SDK v1 to v2 and found that the image upload is failing with the following error:
operation error S3: PutObject, https response error StatusCode: 403, RequestID: XXXXXXXXXXX, HostID: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX, api error SignatureDoesNotMatch: The request signature we calculated does not match the signature you provided. Check your key and signing method.
UPDATED:
I have aws credentials on my home folder in linux in .aws folder in the following format:
[default]
aws_access_key_id = XXXXXXXXXXXXXXXXXXX
aws_secret_access_key = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXx
Here is the code:
package main
import (
"context"
"fmt"
"io"
"net/http"
"github.com/aws/aws-sdk-go-v2/aws"
awsconfig "github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/feature/s3/manager"
"github.com/aws/aws-sdk-go-v2/service/s3"
)
func main() {
fileName := "test123.jpg"
filePath := "/BUCKET_NAME/uploads/aman/2021/6/25/"
res, err := http.Get("https://images.app.goo.gl/mpQ5nXYXjdUMKGgW7")
if err != nil || res.StatusCode != 200 {
// handle errors
}
defer res.Body.Close()
UploadFileInS3Bucket(res.Body, fileName, filePath)
}
func UploadFileInS3Bucket(file io.Reader, fileName, filePath string) {
cfg, err := awsconfig.LoadDefaultConfig(context.TODO(),
awsconfig.WithRegion("REGION"),
)
client := s3.NewFromConfig(cfg)
uploader := manager.NewUploader(client)
uploadResp, err := uploader.Upload(context.TODO(), &s3.PutObjectInput{
Bucket: aws.String(filePath),
Key: aws.String(fileName),
Body: file,
ContentType: aws.String("image"),
})
fmt.Println(uploadResp)
fmt.Println(err)
}
I did not change any credentials/buckets/regions in my code.However if I run the code with SDK v1 then it works fine & images are uploading.
What is going wrong with the SDK v2 ?
After spending a couple of days, I came to know that SDK V2 takes following format for Bucket & Key field:
fileName := "uploads/2021/6/25/test123.jpg"
filePath := "BUCKET_NAME"
Basically for these fields there is vice versa behaviour in SDK V1 & V2. Above is the V2. Below is the V1:
fileName := "test123.jpg"
filePath := "/BUCKET_NAME/uploads/2021/6/25/"
Is it possible to use profile from aws config files (.aws and configuration) directly in Go app, without setting any environment variables, like AWS_SDK_LOAD_CONFIG, AWS_PROFILE or any other environment variable containing plain text credentials?
region := "xxxxxx"
profile := "xxxxxx"
sess, err := session.NewSessionWithOptions(session.Options{
Config: aws.Config{Region: aws.String(region),
CredentialsChainVerboseErrors: aws.Bool(true)},
Profile: profile,
})
Response is this:
NoCredentialProviders: no valid providers in chain
caused by: EnvAccessKeyNotFound: failed to find credentials in the environment.
SharedCredsLoad: failed to load profile, xxxxxxxxxx.
EC2RoleRequestError: no EC2 instance role found
caused by: RequestError: send request failed
AS per the documentation yes, you can provide profile while creating the session.
Credential and config loading order
By default NewSession will only load credentials from the shared credentials file (~/.aws/credentials). If the AWS_SDK_LOAD_CONFIG environment variable is set to a truthy value the Session will be created from the configuration values from the shared config (~/.aws/config) and shared credentials (~/.aws/credentials) files. Using the NewSessionWithOptions with SharedConfigState set to SharedConfigEnable will create the session as if the AWS_SDK_LOAD_CONFIG environment variable was set.
The Environment variables for credentials will have precedence over shared config even if SharedConfig is enabled. To override this behavior, and use shared config credentials instead specify the session.Options.Profile, (e.g. when using credential_source=Environment to assume a role).
sess, err := session.NewSessionWithOptions(session.Options{
Profile: "myProfile",
})
sample code:
package main
import (
"fmt"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/s3"
)
func main() {
region := "eu-central-1"
profile := "myprofile"
sess, err := session.NewSessionWithOptions(session.Options{
Config: aws.Config{Region: aws.String(region),
CredentialsChainVerboseErrors: aws.Bool(true)},
Profile: profile,
})
if err != nil {
fmt.Println(err)
}
svc := s3.New(sess)
_, err = svc.CreateBucket(&s3.CreateBucketInput{
Bucket: aws.String("myxplbukcet"),
})
if err != nil {
fmt.Println(err.Error())
return
}
}
It looks like Go is trying to use the shared credentials file but it's not able to find the appropriate profile. Can you check on your credentials file and look at the profiles available?