From 40e96bcfaa5bcc165d933d0a8a2c30f1fc2e3ab2 Mon Sep 17 00:00:00 2001 From: Link Dupont Date: Thu, 18 Jan 2024 13:01:08 -0500 Subject: [PATCH] feat: Support generating service_account records Add support for generating ServiceAccount type identity records. --- example_test.go | 24 ++++++++++--- identity.go | 21 ++++++++++++ service_account.go | 33 ++++++++++++++++++ service_account_test.go | 76 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 149 insertions(+), 5 deletions(-) create mode 100644 service_account.go create mode 100644 service_account_test.go diff --git a/example_test.go b/example_test.go index 17d7494..a74f30b 100644 --- a/example_test.go +++ b/example_test.go @@ -18,7 +18,7 @@ func ExampleAssociate() { panic(err) } fmt.Println(string(data)) - //Output: {"identity":{"employee_account_number":"02299","org_id":"41123","internal":{"org_id":""},"user":{"username":"","email":"","first_name":"","last_name":"","is_active":false,"is_org_admin":false,"is_internal":false,"locale":"","user_id":""},"system":{},"associate":{"Role":null,"email":"winnifredwinning@shred.org","givenName":"Cameron","rhatUUID":"00e3c758-1d7d-4ecd-98a2-997157e2d05c","surname":"Swift"},"x509":{"subject_dn":"","issuer_dn":""},"type":"Associate","auth_type":"basic-auth"}} + //Output: {"identity":{"employee_account_number":"02299","org_id":"41123","internal":{"org_id":""},"user":{"username":"","email":"","first_name":"","last_name":"","is_active":false,"is_org_admin":false,"is_internal":false,"locale":"","user_id":""},"system":{},"associate":{"Role":null,"email":"winnifredwinning@shred.org","givenName":"Cameron","rhatUUID":"00e3c758-1d7d-4ecd-98a2-997157e2d05c","surname":"Swift"},"x509":{"subject_dn":"","issuer_dn":""},"service_account":{"client_id":"","username":""},"type":"Associate","auth_type":"basic-auth"},"entitlements":null} } func ExampleInternal() { @@ -32,7 +32,7 @@ func ExampleInternal() { panic(err) } fmt.Println(string(data)) - //Output: {"identity":{"org_id":"03797","internal":{"org_id":"08321","auth_time":-2978345600000000000},"user":{"username":"","email":"","first_name":"","last_name":"","is_active":false,"is_org_admin":false,"is_internal":false,"locale":"","user_id":""},"system":{},"associate":{"Role":null,"email":"","givenName":"","rhatUUID":"","surname":""},"x509":{"subject_dn":"","issuer_dn":""},"type":"Internal","auth_type":"basic-auth"}} + //Output: {"identity":{"org_id":"03797","internal":{"org_id":"08321","auth_time":-2978345600000000000},"user":{"username":"","email":"","first_name":"","last_name":"","is_active":false,"is_org_admin":false,"is_internal":false,"locale":"","user_id":""},"system":{},"associate":{"Role":null,"email":"","givenName":"","rhatUUID":"","surname":""},"x509":{"subject_dn":"","issuer_dn":""},"service_account":{"client_id":"","username":""},"type":"Internal","auth_type":"basic-auth"},"entitlements":null} } func ExampleSystem() { @@ -46,7 +46,7 @@ func ExampleSystem() { panic(err) } fmt.Println(string(data)) - //Output: {"identity":{"account_number":"16398","org_id":"57572","internal":{"org_id":"57572"},"user":{"username":"","email":"","first_name":"","last_name":"","is_active":false,"is_org_admin":false,"is_internal":false,"locale":"","user_id":""},"system":{"cn":"It6P","cert_type":"consumer","cluster_id":"x8LdjPo"},"associate":{"Role":null,"email":"","givenName":"","rhatUUID":"","surname":""},"x509":{"subject_dn":"","issuer_dn":""},"type":"System","auth_type":"basic-auth"}} + //Output: {"identity":{"account_number":"16398","org_id":"57572","internal":{"org_id":"57572"},"user":{"username":"","email":"","first_name":"","last_name":"","is_active":false,"is_org_admin":false,"is_internal":false,"locale":"","user_id":""},"system":{"cn":"It6P","cert_type":"consumer","cluster_id":"x8LdjPo"},"associate":{"Role":null,"email":"","givenName":"","rhatUUID":"","surname":""},"x509":{"subject_dn":"","issuer_dn":""},"service_account":{"client_id":"","username":""},"type":"System","auth_type":"basic-auth"},"entitlements":null} } func ExampleUser() { @@ -60,7 +60,7 @@ func ExampleUser() { panic(err) } fmt.Println(string(data)) - //Output: {"identity":{"org_id":"23807","internal":{"org_id":"23807"},"user":{"username":"tycoon","email":"fransen@crump.biz","first_name":"Frankie","last_name":"Collins","is_active":false,"is_org_admin":false,"is_internal":true,"locale":"pi","user_id":"backset"},"system":{},"associate":{"Role":null,"email":"","givenName":"","rhatUUID":"","surname":""},"x509":{"subject_dn":"","issuer_dn":""},"type":"User","auth_type":"cert-auth"}} + //Output: {"identity":{"org_id":"23807","internal":{"org_id":"23807"},"user":{"username":"tycoon","email":"fransen@crump.biz","first_name":"Frankie","last_name":"Collins","is_active":false,"is_org_admin":false,"is_internal":true,"locale":"pi","user_id":"backset"},"system":{},"associate":{"Role":null,"email":"","givenName":"","rhatUUID":"","surname":""},"x509":{"subject_dn":"","issuer_dn":""},"service_account":{"client_id":"","username":""},"type":"User","auth_type":"cert-auth"},"entitlements":null} } func ExampleX509() { @@ -74,5 +74,19 @@ func ExampleX509() { panic(err) } fmt.Println(string(data)) - //Output: {"identity":{"org_id":"23807","internal":{"org_id":""},"user":{"username":"","email":"","first_name":"","last_name":"","is_active":false,"is_org_admin":false,"is_internal":false,"locale":"","user_id":""},"system":{},"associate":{"Role":null,"email":"","givenName":"","rhatUUID":"","surname":""},"x509":{"subject_dn":"2","issuer_dn":"3sfSj"},"type":"X509","auth_type":"cert-auth"}} + //Output: {"identity":{"org_id":"23807","internal":{"org_id":""},"user":{"username":"","email":"","first_name":"","last_name":"","is_active":false,"is_org_admin":false,"is_internal":false,"locale":"","user_id":""},"system":{},"associate":{"Role":null,"email":"","givenName":"","rhatUUID":"","surname":""},"x509":{"subject_dn":"2","issuer_dn":"3sfSj"},"service_account":{"client_id":"","username":""},"type":"X509","auth_type":"cert-auth"},"entitlements":null} +} + +func ExampleServiceAccount() { + xrhidgen.SetSeed(103) + id, err := xrhidgen.NewServiceAccountIdentity(xrhidgen.Identity{}, xrhidgen.ServiceAccount{}) + if err != nil { + panic(err) + } + data, err := json.Marshal(id) + if err != nil { + panic(err) + } + fmt.Println(string(data)) + //Output: {"identity":{"org_id":"23807","internal":{"org_id":""},"user":{"username":"","email":"","first_name":"","last_name":"","is_active":false,"is_org_admin":false,"is_internal":false,"locale":"","user_id":""},"system":{},"associate":{"Role":null,"email":"","givenName":"","rhatUUID":"","surname":""},"x509":{"subject_dn":"","issuer_dn":""},"service_account":{"client_id":"2","username":"crump"},"type":"ServiceAccount","auth_type":"cert-auth"},"entitlements":null} } diff --git a/identity.go b/identity.go index 1def4a8..d130fc9 100644 --- a/identity.go +++ b/identity.go @@ -165,3 +165,24 @@ func NewUserIdentity(identityTemplate Identity, userTemplate User) (*identity.XR return id, nil } + +// NewServiceAccountIdentity will build and return a fully populated +// ServiceAccount identity record, using any values that are present in +// identityTemplate and serviceAccountTemplate. +func NewServiceAccountIdentity(identityTemplate Identity, serviceAccountTemplate ServiceAccount) (*identity.XRHID, error) { + id, err := NewIdentity(identityTemplate) + if err != nil { + return nil, err + } + + serviceAccount, err := NewServiceAccount(serviceAccountTemplate) + if err != nil { + return nil, err + } + + id.Identity.ServiceAccount = *serviceAccount + + id.Identity.Type = "ServiceAccount" + + return id, nil +} diff --git a/service_account.go b/service_account.go new file mode 100644 index 0000000..c05cdfe --- /dev/null +++ b/service_account.go @@ -0,0 +1,33 @@ +package xrhidgen + +import ( + "github.com/pioz/faker" + "github.com/redhatinsights/platform-go-middlewares/v2/identity" +) + +// ServiceAccount holds values to be used as input when generating a service +// account identity record. +type ServiceAccount struct { + ClientID *string + Username *string +} + +// NewServiceAccount will build and return a fully populated ServiceAccount data +// structure, using any values that are present in template. +func NewServiceAccount(template ServiceAccount) (*identity.ServiceAccount, error) { + var id identity.ServiceAccount + + if template.ClientID != nil { + id.ClientId = *template.ClientID + } else { + id.ClientId = faker.String() + } + + if template.Username != nil { + id.Username = *template.Username + } else { + id.Username = faker.Username() + } + + return &id, nil +} diff --git a/service_account_test.go b/service_account_test.go new file mode 100644 index 0000000..93a6278 --- /dev/null +++ b/service_account_test.go @@ -0,0 +1,76 @@ +package xrhidgen + +import ( + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/pioz/faker" + "github.com/redhatinsights/platform-go-middlewares/v2/identity" + "go.openly.dev/pointy" +) + +func TestNewServiceAccount(t *testing.T) { + type Tests struct { + description string + seed int64 + input ServiceAccount + want *identity.ServiceAccount + wantError error + } + tests := []Tests{ + { + description: "empty template", + seed: 100, + input: ServiceAccount{}, + want: &identity.ServiceAccount{ + ClientId: "gimwu7Re", + Username: "boltrope", + }, + }, + { + description: "partial template", + seed: 100, + input: ServiceAccount{ + ClientID: pointy.String("12345"), + }, + want: &identity.ServiceAccount{ + ClientId: "12345", + Username: "ammon", + }, + }, + { + description: "full template", + seed: 100, + input: ServiceAccount{ + ClientID: pointy.String("12345"), + Username: pointy.String("jsmith"), + }, + want: &identity.ServiceAccount{ + ClientId: "12345", + Username: "jsmith", + }, + }, + } + + for _, test := range tests { + t.Run(test.description, func(t *testing.T) { + faker.SetSeed(test.seed) + + got, err := NewServiceAccount(test.input) + + if test.wantError != nil { + if !cmp.Equal(err, test.wantError, cmpopts.EquateErrors()) { + t.Errorf("%#v != %#v", err, test.wantError) + } + } else { + if err != nil { + t.Fatal(err) + } + if !cmp.Equal(got, test.want) { + t.Errorf("%v", cmp.Diff(got, test.want)) + } + } + }) + } +}