Skip to content

Commit

Permalink
rebase off master
Browse files Browse the repository at this point in the history
  • Loading branch information
carrala committed May 10, 2021
2 parents aa6c215 + 38ad962 commit 714daec
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 64 deletions.
160 changes: 104 additions & 56 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,14 @@ const (
SecretValueDataKey = "secretValue"
)

const (
FileSecretType = "File"
CredentialSecretType = "Credential"
ClientSecretType = "Client"
)

var (
SecretTypes = []string{"Client", "Credential", "File"}
SecretTypes = []string{ClientSecretType, CredentialSecretType, FileSecretType}
)

type akCacheKey struct {
Expand Down Expand Up @@ -680,16 +686,25 @@ type ToznySDKV3 struct {
// Network location of the Tozny services to communicate with.
APIEndpoint string
// Tozny server defined globally unique id for this Client.
ClientID string
config e3dbClients.ClientConfig
ClientID string
CurrentIdentity TozIDSessionIdentityData
config e3dbClients.ClientConfig
}

// LoggedInIdentityData represents data about the identity session of a given user. Currently that is just realm and
// username but in the future may include tokens
type TozIDSessionIdentityData struct {
Username string `json:"username"`
Realm string `json:"realm"`
}

// ToznySDKConfig wraps parameters needed to configure a ToznySDK
type ToznySDKConfig struct {
e3dbClients.ClientConfig
AccountUsername string `json:"account_username"`
AccountPassword string `json:"account_password"`
APIEndpoint string `json:"api_url"`
TozIDSessionIdentityData `json:"toz_id_session_identity_data"`
AccountUsername string `json:"account_username"`
AccountPassword string `json:"account_password"`
APIEndpoint string `json:"api_url"`
}

// NewToznySDK returns a new instance of the ToznySDK initialized with the provided
Expand All @@ -709,6 +724,7 @@ func NewToznySDKV3(config ToznySDKConfig) (*ToznySDKV3, error) {
AccountPassword: config.AccountPassword,
APIEndpoint: config.APIEndpoint,
ClientID: config.ClientID,
CurrentIdentity: config.TozIDSessionIdentityData,
config: config.ClientConfig,
}, nil
}
Expand Down Expand Up @@ -755,6 +771,10 @@ func sdkV3FromConfig(config ToznySDKJSONConfig) (*ToznySDKV3, error) {
AccountUsername: config.AccountUsername,
AccountPassword: config.AccountPassword,
APIEndpoint: config.APIBaseURL,
TozIDSessionIdentityData: TozIDSessionIdentityData{
Username: config.Username,
Realm: config.Realm,
},
})
}

Expand Down Expand Up @@ -893,6 +913,8 @@ func GetSDKV3ForTozIDUser(login TozIDLoginRequest) (*ToznySDKV3, error) {
if err != nil {
return nil, err
}
config.Realm = realmInfo.Name
config.Username = username
return sdkV3FromConfig(config)

}
Expand Down Expand Up @@ -965,6 +987,10 @@ func (c *ToznySDKV3) StoreConfigFile(path string) error {
PrivateSigningKey: c.config.SigningKeys.Private.Material,
AccountUsername: c.AccountUsername,
AccountPassword: c.AccountPassword,
TozIDSessionIdentityData: TozIDSessionIdentityData{
Username: c.CurrentIdentity.Username,
Realm: c.CurrentIdentity.Realm,
},
}
return saveJson(path, config)
}
Expand Down Expand Up @@ -1446,7 +1472,7 @@ func (c *ToznySDKV3) CreateSecret(ctx context.Context, secret CreateSecretOption
"version": timestamp,
}
var createdRecord *pdsClient.Record
if secret.SecretType == "File" {
if secret.SecretType == FileSecretType {
writeFileRequest := WriteFileOptions{
RecordType: recordType,
Plain: plain,
Expand Down Expand Up @@ -1766,13 +1792,13 @@ func ValidateSecret(secret CreateSecretOptions) error {
if !matched {
return errors.New("Secret name must contain 1-50 alphanumeric characters, -, or _")
}
if secret.SecretValue == "" && secret.SecretType == "Credential" {
if secret.SecretValue == "" && secret.SecretType == CredentialSecretType {
return errors.New("Value cannot be empty")
}
if secret.SecretType == "File" && strings.TrimSpace(secret.SecretName) == "" {
if secret.SecretType == FileSecretType && strings.TrimSpace(secret.SecretName) == "" {
return errors.New("File name cannot be empty")
}
if secret.SecretType == "Client" {
if secret.SecretType == ClientSecretType {
err := VerifyRawClientCredentials(secret.SecretValue)
if err != nil {
return err
Expand Down Expand Up @@ -1891,52 +1917,62 @@ func (c *ToznySDKV3) ListSecrets(ctx context.Context, options ListSecretsOptions
if len(responseList.Groups) < 1 {
return sharedSecrets, nil
}
sharedSecretList := []Secret{}
var sharedSecretList []Secret
sharedSecretIDs := make(map[string]bool)
for _, group := range responseList.Groups {
if !ValidToznySecretNamespace(group.Name) {
continue
}
listRequest := storageClient.ListGroupRecordsRequest{
GroupID: group.GroupID,
Max: options.Limit,
}
listGroupRecords, err := c.StorageClient.GetSharedWithGroup(ctx, listRequest)
if err != nil {
return nil, err
}
// Add records shared with this group to the list of secrets the user can view.
for _, record := range listGroupRecords.ResultList {
// If this record has already been found and added to the list, skip it
_, exists := sharedSecretIDs[record.Metadata.RecordID]
if exists {
continue
}
var shared string
if group.MemberCount > 1 {
shared = "Yes"
} else {
shared = "No"
}
// find the username for secret writer if it's someone else
searchParams := identityClient.SearchRealmIdentitiesRequest{
RealmName: options.RealmName,
IdentityClientIDs: []uuid.UUID{uuid.MustParse(record.Metadata.WriterID)},
}
identities, err := c.E3dbIdentityClient.SearchRealmIdentities(ctx, searchParams)
for {
listGroupRecords, err := c.StorageClient.GetSharedWithGroup(ctx, listRequest)
if err != nil {
return nil, err
}
username := identities.SearchedIdentitiesInformation[0].RealmUsername
record.Metadata.Plain[SecretWriterUsernameMetadataKey] = username
record.Metadata.Plain[SecretSharedMetadataKey] = shared
// Decrypt the record & add to the list of secrets
recordDecrypted, err := c.DecryptTextSecret(ctx, &record)
if err != nil {
return nil, err
// Add records shared with this group to the list of secrets the user can view.
for _, record := range listGroupRecords.ResultList {
// If this record has already been found and added to the list, skip it
_, exists := sharedSecretIDs[record.Metadata.RecordID]
if exists {
continue
}
var shared string
if group.MemberCount > 1 {
shared = "Yes"
} else {
shared = "No"
}
// find the username for secret writer if it's someone else
searchParams := identityClient.SearchRealmIdentitiesRequest{
RealmName: options.RealmName,
IdentityClientIDs: []uuid.UUID{uuid.MustParse(record.Metadata.WriterID)},
}
identities, err := c.E3dbIdentityClient.SearchRealmIdentities(ctx, searchParams)
if err != nil {
return nil, err
}
username := identities.SearchedIdentitiesInformation[0].RealmUsername
record.Metadata.Plain[SecretWriterUsernameMetadataKey] = username
record.Metadata.Plain[SecretSharedMetadataKey] = shared
// Decrypt the record & add to the list of secrets
recordDecrypted, err := c.DecryptTextSecret(ctx, &record)
if err != nil {
return nil, err
}
secretDecrypted := c.MakeSecretResponse(recordDecrypted, group.GroupID.String(), username)
sharedSecretList = append(sharedSecretList, *secretDecrypted)
sharedSecretIDs[record.Metadata.RecordID] = true
}
secretDecrypted := c.MakeSecretResponse(recordDecrypted, group.GroupID.String(), username)
sharedSecretList = append(sharedSecretList, *secretDecrypted)
sharedSecretIDs[record.Metadata.RecordID] = true

if listGroupRecords.NextToken == "0" {
break
} else {
listRequest.NextToken = listGroupRecords.NextToken
}

}
}
sharedSecrets.List = sharedSecretList
Expand All @@ -1945,7 +1981,8 @@ func (c *ToznySDKV3) ListSecrets(ctx context.Context, options ListSecretsOptions
}

type ViewSecretOptions struct {
SecretID uuid.UUID
SecretID uuid.UUID
MaxSecrets int
}

// ViewSecret returns the decrypted secret with secretID
Expand All @@ -1959,23 +1996,34 @@ func (c *ToznySDKV3) ViewSecret(ctx context.Context, options ViewSecretOptions)
}
var secret *pdsClient.ListedRecord
var groupID string
var nextToken string
for _, group := range groupList.Groups {
listRequest := storageClient.ListGroupRecordsRequest{
GroupID: group.GroupID,
GroupID: group.GroupID,
NextToken: nextToken,
Max: options.MaxSecrets,
}
listGroupRecords, err := c.StorageClient.GetSharedWithGroup(ctx, listRequest)
if err != nil {
return nil, err
}
for _, record := range listGroupRecords.ResultList {
if record.Metadata.RecordID == options.SecretID.String() {
secret = &record
groupID = group.GroupID.String()
for {
listGroupRecords, err := c.StorageClient.GetSharedWithGroup(ctx, listRequest)
if err != nil {
return nil, err
}
for _, record := range listGroupRecords.ResultList {
if record.Metadata.RecordID == options.SecretID.String() {
secret = &record
groupID = group.GroupID.String()
break
}
}
if listGroupRecords.NextToken == "0" {
break
} else {
listRequest.NextToken = listGroupRecords.NextToken
}
}
}
if secret == nil {
return nil, fmt.Errorf("ViewSecret: could not find secret")
return nil, fmt.Errorf("the requested secret could not be found: %s", options.SecretID)
}
recordDecrypted, err := c.DecryptTextSecret(ctx, secret)
if err != nil {
Expand Down Expand Up @@ -2021,7 +2069,7 @@ func (c *ToznySDKV3) MakeSecretResponse(secretRecord *pdsClient.Record, groupID
OwnerUsername: ownerUsername,
// RealmName: c.RealmName,
}
if secret.SecretType == "File" {
if secret.SecretType == FileSecretType {
secret.FileName = secretRecord.Metadata.Plain[SecretFilenameMetadataKey]
} else {
secret.SecretValue = secretRecord.Data[SecretValueDataKey]
Expand Down
1 change: 1 addition & 0 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ Interface is rapidly evolving.
type ToznySDKJSONConfig struct {
// Embed all config for v1 and v2 clients
ConfigFile
TozIDSessionIdentityData `json:"toz_id_session_identity_data"`
PublicSigningKey string `json:"public_signing_key"`
PrivateSigningKey string `json:"private_signing_key"`
AccountUsername string `json:"account_user_name"`
Expand Down
18 changes: 10 additions & 8 deletions secrets_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func TestCreateAndListSecrets(t *testing.T) {
}
secretReq := CreateSecretOptions{
SecretName: fmt.Sprintf("client-%s", uuid.New().String()),
SecretType: "Credential",
SecretType: CredentialSecretType,
SecretValue: uuid.New().String(),
Description: "a credential test",
RealmName: realmName,
Expand All @@ -55,7 +55,7 @@ func TestCreateAndListSecrets(t *testing.T) {
}`
secretReq2 := CreateSecretOptions{
SecretName: fmt.Sprintf("cred-%s", uuid.New().String()),
SecretType: "Client",
SecretType: ClientSecretType,
SecretValue: validClient,
Description: "a client cred test",
RealmName: realmName,
Expand All @@ -70,7 +70,7 @@ func TestCreateAndListSecrets(t *testing.T) {
}
listOptions := ListSecretsOptions{
RealmName: realmName,
Limit: 30,
Limit: 1000,
NextToken: 0,
}
listSecrets, err := sdk.ListSecrets(testCtx, listOptions)
Expand Down Expand Up @@ -118,7 +118,7 @@ func TestInvalidCredSecretFails(t *testing.T) {
}`
secretReq := CreateSecretOptions{
SecretName: fmt.Sprintf("cred-%s", uuid.New().String()),
SecretType: "Client",
SecretType: ClientSecretType,
SecretValue: invalidClient,
Description: "a client cred test",
RealmName: realmName,
Expand All @@ -140,7 +140,7 @@ func TestInvalidCredSecretFails(t *testing.T) {
}`
secretReq = CreateSecretOptions{
SecretName: fmt.Sprintf("cred-%s", uuid.New().String()),
SecretType: "Client",
SecretType: ClientSecretType,
SecretValue: invalidClient,
Description: "a client cred test",
RealmName: realmName,
Expand All @@ -165,7 +165,7 @@ func TestCreateAndViewSecretSucceeds(t *testing.T) {
}
secretReq := CreateSecretOptions{
SecretName: fmt.Sprintf("client-%s", uuid.New().String()),
SecretType: "Credential",
SecretType: CredentialSecretType,
SecretValue: uuid.New().String(),
Description: "a credential test",
RealmName: realmName,
Expand All @@ -175,7 +175,8 @@ func TestCreateAndViewSecretSucceeds(t *testing.T) {
t.Fatalf("Could not create secret: Req: %+v Err: %+v", secretReq, err)
}
viewOptions := ViewSecretOptions{
SecretID: secretCreated.SecretID,
SecretID: secretCreated.SecretID,
MaxSecrets: 1000,
}
secretView, err := sdk.ViewSecret(testCtx, viewOptions)
if err != nil {
Expand Down Expand Up @@ -215,7 +216,8 @@ func TestCreateAndReadFileSecretSucceeds(t *testing.T) {
}
secretReq := CreateSecretOptions{
SecretName: fmt.Sprintf("client-%s", uuid.New().String()),
SecretType: "File",
SecretType: FileSecretType,
SecretValue: "",
Description: "a file test",
FileName: plaintextFileName,
RealmName: realmName,
Expand Down

0 comments on commit 714daec

Please sign in to comment.