AWS Go SDK not finding the credentials file at C:/###/.aws/credentials - amazon-web-services

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.

Related

Amazon SQS:: Got an error while trying to create queue: NoCredentialProviders: no valid providers in chain. Deprecated

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.

Image upload failed using AWS SDK V2 in GO

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/"

Use AWS Go SDK with profile

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?

x509: certificate signed by unknown authority using AWS IoT

When trying to publish a message to a topic using the AWS IoT SDK for go I get the following error: "x509: certificate signed by unknown authority".
I am on windows and all I did was install different root CA's (literally via doubleclick) and a device certificate generated by AWS IoT Console.
I feel like I should somehow specify the path to the certificate but unlike the Python SDk the one for go does not mention that anywhere. I also added my credentials via the AWS Cli so that should not be the issue.
package main
import (
"fmt"
"log"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/iotdataplane"
)
func main() {
sess, err := session.NewSession(&aws.Config{
Region: aws.String("eu-central-1"), Endpoint: aws.String("xxxxxxxxxx.iot.eu-central-1.amazonaws.com")},
)
if err != nil {
log.Fatal(err)
}
iotDataSvc := iotdataplane.New(sess)
input := &iotdataplane.PublishInput{
Payload: []byte(`{
'state': {
'desired':{
'humidity':10,
'temp':10
}
}
}`),
Topic: aws.String("/update"),
Qos: aws.Int64(0),
}
resp, err := iotDataSvc.Publish(input)
if err != nil {
log.Fatal(err)
}
fmt.Println(resp)
}
Found the mistake: xxxxxxxxxx.iot.eu-central-1.amazonaws.com needs to be xxxxxxxxxx-ats.iot.eu-central-1.amazonaws.com.

How to run AWS SDK with credentials from variables?

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", ""),
}))
}