Skip to content

Commit

Permalink
Add support for credential_process (#1716)
Browse files Browse the repository at this point in the history
Fixes #1485

Signed-off-by: Harshavardhana <harsha@minio.io>
  • Loading branch information
harshavardhana committed Oct 25, 2022
1 parent 4acfae7 commit fbe9d3e
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 5 deletions.
7 changes: 7 additions & 0 deletions pkg/credentials/credentials.json
@@ -0,0 +1,7 @@
{
"Version": 1,
"SessionToken": "token",
"AccessKeyId": "accessKey",
"SecretAccessKey": "secret",
"Expiration": "9999-04-27T16:02:25.000Z"
}
3 changes: 3 additions & 0 deletions pkg/credentials/credentials.sample
Expand Up @@ -10,3 +10,6 @@ aws_secret_access_key = secret
[with_colon]
aws_access_key_id: accessKey
aws_secret_access_key: secret

[with_process]
credential_process = /bin/cat credentials.json
48 changes: 43 additions & 5 deletions pkg/credentials/file_aws_credentials.go
Expand Up @@ -18,17 +18,33 @@
package credentials

import (
"encoding/json"
"errors"
"os"
"os/exec"
"path/filepath"
"strings"
"time"

ini "gopkg.in/ini.v1"
)

// A externalProcessCredentials stores the output of a credential_process
type externalProcessCredentials struct {
Version int
SessionToken string
AccessKeyID string `json:"AccessKeyId"`
SecretAccessKey string
Expiration time.Time
}

// A FileAWSCredentials retrieves credentials from the current user's home
// directory, and keeps track if those credentials are expired.
//
// Profile ini file example: $HOME/.aws/credentials
type FileAWSCredentials struct {
Expiry

// Path to the shared credentials file.
//
// If empty will look for "AWS_SHARED_CREDENTIALS_FILE" env variable. If the
Expand Down Expand Up @@ -89,6 +105,33 @@ func (p *FileAWSCredentials) Retrieve() (Value, error) {
// Default to empty string if not found.
token := iniProfile.Key("aws_session_token")

// If credential_process is defined, obtain credentials by executing
// the external process
credentialProcess := strings.TrimSpace(iniProfile.Key("credential_process").String())
if credentialProcess != "" {
args := strings.Fields(credentialProcess)
if len(args) <= 1 {
return Value{}, errors.New("invalid credential process args")
}
cmd := exec.Command(args[0], args[1:]...)
out, err := cmd.Output()
if err != nil {
return Value{}, err
}
var externalProcessCredentials externalProcessCredentials
err = json.Unmarshal([]byte(out), &externalProcessCredentials)
if err != nil {
return Value{}, err
}
p.retrieved = true
p.SetExpiration(externalProcessCredentials.Expiration, DefaultExpiryWindow)
return Value{
AccessKeyID: externalProcessCredentials.AccessKeyID,
SecretAccessKey: externalProcessCredentials.SecretAccessKey,
SessionToken: externalProcessCredentials.SessionToken,
SignerType: SignatureV4,
}, nil
}
p.retrieved = true
return Value{
AccessKeyID: id.String(),
Expand All @@ -98,11 +141,6 @@ func (p *FileAWSCredentials) Retrieve() (Value, error) {
}, nil
}

// IsExpired returns if the shared credentials have expired.
func (p *FileAWSCredentials) IsExpired() bool {
return !p.retrieved
}

// loadProfiles loads from the file pointed to by shared credentials filename for profile.
// The credentials retrieved from the profile will be returned or error. Error will be
// returned if it fails to read from the file, or the data is invalid.
Expand Down
21 changes: 21 additions & 0 deletions pkg/credentials/file_test.go
Expand Up @@ -120,6 +120,27 @@ func TestFileAWS(t *testing.T) {
if !creds.IsExpired() {
t.Error("Should be expired if not loaded")
}

os.Clearenv()

creds = NewFileAWSCredentials("credentials.sample", "with_process")
credValues, err = creds.Get()
if err != nil {
t.Fatal(err)
}

if credValues.AccessKeyID != "accessKey" {
t.Errorf("Expected 'accessKey', got %s'", credValues.AccessKeyID)
}
if credValues.SecretAccessKey != "secret" {
t.Errorf("Expected 'secret', got %s'", credValues.SecretAccessKey)
}
if credValues.SessionToken != "token" {
t.Errorf("Expected 'token', got %s'", credValues.SessionToken)
}
if creds.IsExpired() {
t.Error("Should not be expired")
}
}

func TestFileMinioClient(t *testing.T) {
Expand Down

0 comments on commit fbe9d3e

Please sign in to comment.