Skip to content

Commit

Permalink
getall was not passing encryption contexts to decrypt functions so no…
Browse files Browse the repository at this point in the history
…t listing available secrets. Also needed to handle secrets that the hmac could not be decrypted due to wrong encryption context.
  • Loading branch information
Richard Adams committed Nov 25, 2016
1 parent b9f4ab3 commit ab1f9f9
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 13 deletions.
4 changes: 2 additions & 2 deletions cmd/unicreds/main.go
Expand Up @@ -160,7 +160,7 @@ func main() {
printFatalError(err)
}
case cmdGetAll.FullCommand():
creds, err := unicreds.GetAllSecrets(dynamoTable, *cmdGetAllVersions)
creds, err := unicreds.GetAllSecrets(dynamoTable, *cmdGetAllVersions, encContext)
if err != nil {
printFatalError(err)
}
Expand Down Expand Up @@ -190,7 +190,7 @@ func main() {
if err != nil {
printFatalError(err)
}
creds, err := unicreds.GetAllSecrets(dynamoTable, *cmdGetAllVersions)
creds, err := unicreds.GetAllSecrets(dynamoTable, *cmdGetAllVersions, encContext)
for _, cred := range creds {
os.Setenv(cred.Name, cred.Secret)
}
Expand Down
25 changes: 16 additions & 9 deletions ds.go
Expand Up @@ -305,12 +305,9 @@ func ListSecrets(tableName *string, allVersions bool) ([]*Credential, error) {
}

// GetAllSecrets returns a list of all secrets
func GetAllSecrets(tableName *string, allVersions bool) ([]*DecryptedCredential, error) {
func GetAllSecrets(tableName *string, allVersions bool, encContext *EncryptionContextValue) ([]*DecryptedCredential, error) {
log.Debug("Getting all secrets")

// build an empty encryption context
encContext := NewEncryptionContextValue()

var items []map[string]*dynamodb.AttributeValue
var lastEvaluatedKey map[string]*dynamodb.AttributeValue

Expand Down Expand Up @@ -360,8 +357,8 @@ func GetAllSecrets(tableName *string, allVersions bool) ([]*DecryptedCredential,
dcred, err := decryptCredential(cred, encContext)
if err != nil {
if awsErr, ok := err.(awserr.Error); ok {
if awsErr.Code() == "AccessDeniedException" {
log.Debugf("KMS Access Denied to decrypt: %s", cred.Name)
if awsErr.Code() == "AccessDeniedException" || awsErr.Code() == "InvalidCiphertextException" {
log.Debugf("%s: %s", err, cred.Name)
continue
}
}
Expand Down Expand Up @@ -471,10 +468,10 @@ func DeleteSecret(tableName *string, name string) error {
_, err = dynamoSvc.DeleteItem(&dynamodb.DeleteItemInput{
TableName: tableName,
Key: map[string]*dynamodb.AttributeValue{
"name": &dynamodb.AttributeValue{
"name": {
S: aws.String(cred.Name),
},
"version": &dynamodb.AttributeValue{
"version": {
S: aws.String(cred.Version),
},
},
Expand Down Expand Up @@ -523,7 +520,17 @@ func decryptCredential(cred *Credential, encContext *EncryptionContextValue) (*D
}

dk, err := DecryptDataKey(wrappedKey, encContext)

if awsErr, ok := err.(awserr.Error); ok {
// Create reasoned responses to assist with debugging
if awsErr.Code() == "AccessDeniedException" {
log.Debugf("KMS Access Denied to decrypt: %s", cred.Name)
err = awserr.New("AccessDeniedException", "KMS Access Denied to decrypt", nil)
}
if awsErr.Code() == "InvalidCiphertextException" {
err = awserr.New("InvalidCiphertextException", "The encryption context provided "+
"may not match the one used when the credential was stored", nil)
}
}
if err != nil {
return nil, err
}
Expand Down
27 changes: 25 additions & 2 deletions ds_test.go
Expand Up @@ -152,7 +152,7 @@ func TestGetAllSecrets(t *testing.T) {
dsMock.On("Scan", mock.AnythingOfType("*dynamodb.ScanInput")).Return(qs, nil)
kmsMock.On("Decrypt", mock.AnythingOfType("*kms.DecryptInput")).Return(ki, nil)

ds, err := GetAllSecrets(&tableName, false)
ds, err := GetAllSecrets(&tableName, false, NewEncryptionContextValue())

assert.Nil(t, err)
assert.Len(t, ds, 1)
Expand All @@ -172,7 +172,30 @@ func TestGetAllSecretsDecryptFailed(t *testing.T) {
dsMock.On("Scan", mock.AnythingOfType("*dynamodb.ScanInput")).Return(qs, nil)
kmsMock.On("Decrypt", mock.AnythingOfType("*kms.DecryptInput")).Return(nil, awsErr)

ds, err := GetAllSecrets(&tableName, true)
ds, err := GetAllSecrets(&tableName, true, NewEncryptionContextValue())

assert.Nil(t, err)
assert.Len(t, ds, 0)
}

func TestGetAllSecretsEncryptionContextFailed(t *testing.T) {

dsMock, kmsMock := configureMock()

qs := &dynamodb.ScanOutput{
Count: aws.Int64(0),
Items: itemsFixture,
}

awsErr := awserr.New("InvalidCiphertextException", "", nil)

dsMock.On("Scan", mock.AnythingOfType("*dynamodb.ScanInput")).Return(qs, nil)
kmsMock.On("Decrypt", mock.AnythingOfType("*kms.DecryptInput")).Return(nil, awsErr)

ec := NewEncryptionContextValue()
ec.Set("Unknown:Context")

ds, err := GetAllSecrets(&tableName, true, ec)

assert.Nil(t, err)
assert.Len(t, ds, 0)
Expand Down

0 comments on commit ab1f9f9

Please sign in to comment.