Skip to content

Commit

Permalink
feat(RAIN-92599): Add AzureAdAl integration support (#1590)
Browse files Browse the repository at this point in the history
- Add support for get and update methods for AzureAdAl integration
- Add unit tests
  • Loading branch information
rubinder-lw authored Mar 14, 2024
1 parent e076880 commit 9e12df9
Show file tree
Hide file tree
Showing 4 changed files with 286 additions and 0 deletions.
59 changes: 59 additions & 0 deletions api/_examples/cloud-accounts/azure-ad-al/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package main

import (
"fmt"
"log"
"os"

"github.com/lacework/go-sdk/api"
)

func main() {
lacework, err := api.NewClient(os.Getenv("LW_ACCOUNT"),
api.WithSubaccount(os.Getenv("LW_SUBACCOUNT")),
api.WithApiKeys(os.Getenv("LW_API_KEY"), os.Getenv("LW_API_SECRET")),
)
if err != nil {
log.Fatal(err)
}

res, err := lacework.V2.CloudAccounts.List()
if err != nil {
log.Fatal(err)
}

for _, account := range res.Data {
support := "Unsupported"
switch account.Type {
case api.AzureAdAlCloudAccount.String():
support = "Supported"
}

// Output: INTEGRATION-GUID:INTEGRATION-TYPE:[Supported|Unsupported]
fmt.Printf("%s:%s:%s\n", account.IntgGuid, account.Type, support)
}

azureAdAlData := api.AzureAdAlData{
Credentials: api.AzureAdAlCredentials{
ClientID: "client-id",
ClientSecret: "some-secret",
},
TenantID: "tenant-id",
EventHubNamespace: "EventHubNamespace",
EventHubName: "EventHubName",
}

azureAdAlCloudAccount := api.NewCloudAccount(
"cloud-from-golang",
api.AzureAdAlCloudAccount,
azureAdAlData,
)

azureAdAlIntegrationResponse, err := lacework.V2.CloudAccounts.Create(azureAdAlCloudAccount)
if err != nil {
log.Fatal(err)
}

// Output: AzureAdAl Cloud Account created: THE-INTEGRATION-GUID
fmt.Printf("Cloud Account created: %s", azureAdAlIntegrationResponse.Data.IntgGuid)
}
2 changes: 2 additions & 0 deletions api/cloud_accounts.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ const (
AwsSidekickOrgCloudAccount
AwsUsGovCfgCloudAccount
AwsUsGovCtSqsCloudAccount
AzureAdAlCloudAccount
AzureAlSeqCloudAccount
AzureCfgCloudAccount
GcpAtSesCloudAccount
Expand All @@ -112,6 +113,7 @@ var CloudAccountTypes = map[cloudAccountType]string{
AwsSidekickOrgCloudAccount: "AwsSidekickOrg",
AwsUsGovCfgCloudAccount: "AwsUsGovCfg",
AwsUsGovCtSqsCloudAccount: "AwsUsGovCtSqs",
AzureAdAlCloudAccount: "AzureAdAl",
AzureAlSeqCloudAccount: "AzureAlSeq",
AzureCfgCloudAccount: "AzureCfg",
GcpAtSesCloudAccount: "GcpAtSes",
Expand Down
59 changes: 59 additions & 0 deletions api/cloud_accounts_azure_ad_al.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
//
// Author:: Rubinder Singh (<rubinder.singh@lacework.net>)
// Copyright:: Copyright 2024, Lacework Inc.
// License:: Apache License, Version 2.0
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

package api

// GetAzureAdAl gets a single AzureAdAl integration matching the
// provided integration guid
func (svc *CloudAccountsService) GetAzureAdAl(guid string) (
response AzureAdAlIntegrationResponse,
err error,
) {
err = svc.get(guid, &response)
return
}

// UpdateAzureAdAl updates a single AzureAdAl integration on the Lacework Server
func (svc *CloudAccountsService) UpdateAzureAdAl(data CloudAccount) (
response AzureAdAlIntegrationResponse,
err error,
) {
err = svc.update(data.ID(), data, &response)
return
}

type AzureAdAlIntegrationResponse struct {
Data AzureAdAl `json:"data"`
}

type AzureAdAl struct {
v2CommonIntegrationData
Data AzureAdAlData `json:"data"`
}

type AzureAdAlData struct {
Credentials AzureAdAlCredentials `json:"credentials"`
TenantID string `json:"tenantId"`
EventHubNamespace string `json:"eventHubNamespace"`
EventHubName string `json:"eventHubName"`
}

type AzureAdAlCredentials struct {
ClientID string `json:"clientId"`
ClientSecret string `json:"clientSecret"`
}
166 changes: 166 additions & 0 deletions api/cloud_accounts_azure_ad_al_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
//
// Author:: Rubinder Singh (<rubinder.singh@lacework.net>)
// Copyright:: Copyright 2024, Lacework Inc.
// License:: Apache License, Version 2.0
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

package api_test

import (
"fmt"
"net/http"
"testing"

"github.com/lacework/go-sdk/api"
"github.com/lacework/go-sdk/internal/intgguid"
"github.com/lacework/go-sdk/internal/lacework"
"github.com/stretchr/testify/assert"
)

func TestCloudAccountsAzureAdAlGet(t *testing.T) {
var (
intgGUID = intgguid.New()
apiPath = fmt.Sprintf("CloudAccounts/%s", intgGUID)
fakeServer = lacework.MockServer()
)
fakeServer.MockToken("TOKEN")
defer fakeServer.Close()

fakeServer.MockAPI(apiPath, func(w http.ResponseWriter, r *http.Request) {
assert.Equal(t, "GET", r.Method, "GetAzureAdAl() should be a GET method")
fmt.Fprintf(w, generateCloudAccountResponse(azureAdAlCloudAccount(intgGUID)))
})

c, err := api.NewClient("test",
api.WithToken("TOKEN"),
api.WithURL(fakeServer.URL()),
)
assert.Nil(t, err)

response, err := c.V2.CloudAccounts.GetAzureAdAl(intgGUID)
assert.Nil(t, err)
assert.NotNil(t, response)
assert.Equal(t, intgGUID, response.Data.IntgGuid)
assert.Equal(t, "azure_ad_al_integration_test", response.Data.Name)
assert.True(t, response.Data.State.Ok)
assert.Equal(t, "123456777", response.Data.Data.Credentials.ClientID)
assert.Equal(t, "test-secret-1234", response.Data.Data.Credentials.ClientSecret)
assert.Equal(t, "AzureAdAl", response.Data.Type)
assert.Equal(t, "tenant-1", response.Data.Data.TenantID)
assert.Equal(t, "eventHubNamespace-1", response.Data.Data.EventHubNamespace)
assert.Equal(t, "eventHubName-1", response.Data.Data.EventHubName)
}

func TestCloudAccountsAzureAdAlUpdate(t *testing.T) {
var (
intgGUID = intgguid.New()
apiPath = fmt.Sprintf("CloudAccounts/%s", intgGUID)
fakeServer = lacework.MockServer()
intgData = api.AzureAdAlData{
TenantID: "tenant-1",
Credentials: api.AzureAdAlCredentials{
ClientID: "123456777",
ClientSecret: "test-secret-1234",
},
EventHubNamespace: "eventHubNamespace-1",
EventHubName: "eventHubName-1",
}
)
fakeServer.MockToken("TOKEN")
defer fakeServer.Close()

// Step 1 - Start Fake Server to return updated data
fakeServer.MockAPI(apiPath, func(w http.ResponseWriter, r *http.Request) {
assert.Equal(t, "PATCH", r.Method, "UpdateAzureAdAl() should be a PATCH method")

if assert.NotNil(t, r.Body) {
body := httpBodySniffer(r)
assert.Contains(t, body, intgGUID, "INTG_GUID missing")
assert.Contains(t, body, "azure_ad_al_integration_test", "cloud account name is missing")
assert.Contains(t, body, "AzureAdAl", "wrong cloud account type")
assert.Contains(t, body, intgData.Credentials.ClientID, "wrong ClientId")
assert.Contains(t, body, intgData.Credentials.ClientSecret, "wrong ClientSecret")
assert.Contains(t, body, intgData.TenantID, "wrong TenantId")
assert.Contains(t, body, intgData.EventHubNamespace, "wrong EventHubNamespace")
assert.Contains(t, body, intgData.EventHubName, "wrong EventHubName")
assert.Contains(t, body, "enabled\":1", "cloud account is not enabled")
}

fmt.Fprintf(w, generateCloudAccountResponse(azureAdAlCloudAccount(intgGUID)))
})

c, err := api.NewClient("test",
api.WithToken("TOKEN"),
api.WithURL(fakeServer.URL()),
)
assert.Nil(t, err)

// Step 2 - Get Updated data from Fake server
cloudAccount := api.NewCloudAccount("azure_ad_al_integration_test",
api.AzureAdAlCloudAccount,
intgData,
)

cloudAccount.IntgGuid = intgGUID
response, err := c.V2.CloudAccounts.UpdateAzureAdAl(cloudAccount)
assert.Nil(t, err, "Cannot update integration")
assert.NotNil(t, response)
integration := response.Data
assert.Equal(t, intgGUID, integration.IntgGuid)

integrationData := integration.Data
assert.Equal(t, "azure_ad_al_integration_test", cloudAccount.Name)
assert.Equal(t, "AzureAdAl", cloudAccount.Type)
assert.Equal(t, 1, cloudAccount.Enabled)
assert.Equal(t, "tenant-1", integrationData.TenantID)
assert.Equal(t, "eventHubNamespace-1", integrationData.EventHubNamespace)
assert.Equal(t, "eventHubName-1", integrationData.EventHubName)
assert.Equal(t, "123456777", integrationData.Credentials.ClientID)
assert.Equal(t, "test-secret-1234", integrationData.Credentials.ClientSecret)
}

func azureAdAlCloudAccount(id string) string {
return fmt.Sprintf(`{
"createdOrUpdatedBy": "rubinder.singh@lacework.net",
"createdOrUpdatedTime": "2024-03-11T00:00:00.000Z",
"enabled": 1,
"intgGuid": %q,
"isOrg": 0,
"name": "azure_ad_al_integration_test",
"state": {
"ok": true,
"lastUpdatedTime": 1710104691000,
"lastSuccessfulTime": 1710104691000,
"details": {
"queueRx": "OK",
"decodeNtfn": "OK",
"logFileGet": "OK",
"queueDel": "OK",
"lastMsgRxTime": 1710104691000,
"noData": true
}
},
"type": "AzureAdAl",
"data": {
"credentials": {
"clientId": "123456777",
"clientSecret": "test-secret-1234"
},
"tenantId": "tenant-1",
"eventHubNamespace": "eventHubNamespace-1",
"eventHubName": "eventHubName-1"
}
}`, id)
}

0 comments on commit 9e12df9

Please sign in to comment.