Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions hack/ark/test-e2e.sh
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ kubectl apply -f "${root_dir}/hack/ark/conjur-connect-configmap.yaml"

# We use a non-existent tag and omit the `--version` flag, to work around a Helm
# v4 bug. See: https://github.com/helm/helm/issues/31600
# TODO: shouldn't need to set config.sendSecretValues because it will default to true in future
helm upgrade agent "oci://${ARK_CHART}:NON_EXISTENT_TAG@${ARK_CHART_DIGEST}" \
--install \
--wait \
Expand All @@ -94,6 +95,7 @@ helm upgrade agent "oci://${ARK_CHART}:NON_EXISTENT_TAG@${ARK_CHART_DIGEST}" \
--set config.clusterName="e2e-test-cluster" \
--set config.clusterDescription="A temporary cluster for E2E testing. Contact @wallrj-cyberark." \
--set config.period=60s \
--set config.sendSecretValues=true \
--set-json "podLabels={\"disco-agent.cyberark.cloud/test-id\": \"${RANDOM}\"}"

kubectl rollout status deployments/disco-agent --namespace "${NAMESPACE}"
Expand Down
12 changes: 6 additions & 6 deletions internal/cyberark/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ func TestCyberArkClient_PutSnapshot_MockAPI(t *testing.T) {
Secret: "somepassword",
}

discoveryClient := servicediscovery.New(httpClient)
discoveryClient := servicediscovery.New(httpClient, cfg.Subdomain)

serviceMap, tenantUUID, err := discoveryClient.DiscoverServices(t.Context(), cfg.Subdomain)
serviceMap, tenantUUID, err := discoveryClient.DiscoverServices(t.Context())
if err != nil {
t.Fatalf("failed to discover mock services: %v", err)
}
Expand All @@ -44,7 +44,7 @@ func TestCyberArkClient_PutSnapshot_MockAPI(t *testing.T) {

err = cl.PutSnapshot(ctx, dataupload.Snapshot{
ClusterID: "ffffffff-ffff-ffff-ffff-ffffffffffff",
AgentVersion: version.PreflightVersion,
AgentVersion: version.CYBRVersion,
})

require.NoError(t, err)
Expand Down Expand Up @@ -76,9 +76,9 @@ func TestCyberArkClient_PutSnapshot_RealAPI(t *testing.T) {
cfg, err := cyberark.LoadClientConfigFromEnvironment()
require.NoError(t, err)

discoveryClient := servicediscovery.New(httpClient)
discoveryClient := servicediscovery.New(httpClient, cfg.Subdomain)

serviceMap, tenantUUID, err := discoveryClient.DiscoverServices(t.Context(), cfg.Subdomain)
serviceMap, tenantUUID, err := discoveryClient.DiscoverServices(t.Context())
if err != nil {
t.Fatalf("failed to discover services: %v", err)
}
Expand All @@ -88,7 +88,7 @@ func TestCyberArkClient_PutSnapshot_RealAPI(t *testing.T) {

err = cl.PutSnapshot(ctx, dataupload.Snapshot{
ClusterID: "ffffffff-ffff-ffff-ffff-ffffffffffff",
AgentVersion: version.PreflightVersion,
AgentVersion: version.CYBRVersion,
})

require.NoError(t, err)
Expand Down
6 changes: 3 additions & 3 deletions internal/cyberark/dataupload/dataupload.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ func (c *CyberArkClient) PutSnapshot(ctx context.Context, snapshot Snapshot) err

req.Header.Set("X-Amz-Tagging", q.Encode())

version.SetUserAgent(req)
version.SetUserAgentCYBR(req)

res, err := c.httpClient.Do(req)
if err != nil {
Expand Down Expand Up @@ -190,7 +190,7 @@ func (c *CyberArkClient) retrievePresignedUploadURL(ctx context.Context, checksu
request := RetrievePresignedUploadURLRequest{
ClusterID: clusterID,
Checksum: checksum,
AgentVersion: version.PreflightVersion,
AgentVersion: version.CYBRVersion,
FileSize: fileSize,
}

Expand All @@ -211,7 +211,7 @@ func (c *CyberArkClient) retrievePresignedUploadURL(ctx context.Context, checksu
return "", "", fmt.Errorf("failed to authenticate request: %s", err)
}

version.SetUserAgent(req)
version.SetUserAgentCYBR(req)

// Add telemetry headers
arkapi.SetTelemetryRequestHeader(req)
Expand Down
2 changes: 1 addition & 1 deletion internal/cyberark/dataupload/dataupload_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ func TestCyberArkClient_PutSnapshot_MockAPI(t *testing.T) {
name: "successful upload",
snapshot: dataupload.Snapshot{
ClusterID: "ffffffff-ffff-ffff-ffff-ffffffffffff",
AgentVersion: version.PreflightVersion,
AgentVersion: version.CYBRVersion,
},
authenticate: setToken("success-token"),
requireFn: func(t *testing.T, err error) {
Expand Down
12 changes: 6 additions & 6 deletions internal/cyberark/dataupload/mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ func randHex() string {
}

func (mds *mockDataUploadServer) handleSnapshotLinks(w http.ResponseWriter, r *http.Request) {
if r.Header.Get("User-Agent") != version.UserAgent() {
if r.Header.Get("User-Agent") != version.UserAgentCYBR() {
http.Error(w, "should set user agent on all requests", http.StatusInternalServerError)
return
}
Expand Down Expand Up @@ -132,7 +132,7 @@ func (mds *mockDataUploadServer) handleSnapshotLinks(w http.ResponseWriter, r *h
return
}

if req.AgentVersion != version.PreflightVersion {
if req.AgentVersion != version.CYBRVersion {
http.Error(w, fmt.Sprintf("post body contains unexpected agent version: %s", req.AgentVersion), http.StatusInternalServerError)
return
}
Expand Down Expand Up @@ -214,7 +214,7 @@ func (mds *mockDataUploadServer) handlePresignedUpload(w http.ResponseWriter, r
return
}

if r.Header.Get("User-Agent") != version.UserAgent() {
if r.Header.Get("User-Agent") != version.UserAgentCYBR() {
http.Error(w, "should set user agent on all requests", http.StatusInternalServerError)
return
}
Expand Down Expand Up @@ -249,8 +249,8 @@ func (mds *mockDataUploadServer) handlePresignedUpload(w http.ResponseWriter, r
return
}

if tags.Get("agent_version") != version.PreflightVersion {
http.Error(w, fmt.Sprintf("x-amz-tagging should contain an agent_version tag with value %s", version.PreflightVersion), http.StatusInternalServerError)
if tags.Get("agent_version") != version.CYBRVersion {
http.Error(w, fmt.Sprintf("x-amz-tagging should contain an agent_version tag with value %s but got %s", version.CYBRVersion, tags.Get("agent_version")), http.StatusInternalServerError)
return
}

Expand Down Expand Up @@ -308,7 +308,7 @@ func (mds *mockDataUploadServer) handlePresignedUpload(w http.ResponseWriter, r
err = d.Decode(&snapshot)
require.NoError(mds.t, err)
assert.Equal(mds.t, successClusterID, snapshot.ClusterID)
assert.Equal(mds.t, version.PreflightVersion, snapshot.AgentVersion)
assert.Equal(mds.t, version.CYBRVersion, snapshot.AgentVersion)

// AWS S3 responds with an empty body if the PUT succeeds
w.WriteHeader(http.StatusOK)
Expand Down
4 changes: 2 additions & 2 deletions internal/cyberark/identity/cmd/testidentity/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ func run(ctx context.Context) error {
var rootCAs *x509.CertPool
httpClient := http_client.NewDefaultClient(version.UserAgent(), rootCAs)

sdClient := servicediscovery.New(httpClient)
services, _, err := sdClient.DiscoverServices(ctx, subdomain)
sdClient := servicediscovery.New(httpClient, subdomain)
services, _, err := sdClient.DiscoverServices(ctx)
if err != nil {
return fmt.Errorf("while performing service discovery: %s", err)
}
Expand Down
2 changes: 1 addition & 1 deletion internal/cyberark/identity/identity_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ func TestLoginUsernamePassword_RealAPI(t *testing.T) {
arktesting.SkipIfNoEnv(t)
subdomain := os.Getenv("ARK_SUBDOMAIN")
httpClient := http.DefaultClient
services, _, err := servicediscovery.New(httpClient).DiscoverServices(t.Context(), subdomain)
services, _, err := servicediscovery.New(httpClient, subdomain).DiscoverServices(t.Context())
require.NoError(t, err)

loginUsernamePasswordTests(t, func(t testing.TB) inputs {
Expand Down
50 changes: 39 additions & 11 deletions internal/cyberark/servicediscovery/discovery.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import (
"net/url"
"os"
"path"
"sync"
"time"

arkapi "github.com/jetstack/preflight/internal/cyberark/api"
"github.com/jetstack/preflight/pkg/version"
Expand All @@ -35,21 +37,34 @@ const (
// users to fetch URLs for various APIs available in CyberArk. This client is specialised to
// fetch only API endpoints, since only API endpoints are required by the Venafi Kubernetes Agent currently.
type Client struct {
client *http.Client
baseURL string
client *http.Client
baseURL string
subdomain string

cachedResponse *Services
cachedTenantID string
cachedResponseTime time.Time
cachedResponseMutex sync.Mutex
}

// New creates a new CyberArk Service Discovery client. If the ARK_DISCOVERY_API
// environment variable is set, it is used as the base URL for the service
// discovery API. Otherwise, the production URL is used.
func New(httpClient *http.Client) *Client {
func New(httpClient *http.Client, subdomain string) *Client {
baseURL := os.Getenv("ARK_DISCOVERY_API")
if baseURL == "" {
baseURL = ProdDiscoveryAPIBaseURL
}

client := &Client{
client: httpClient,
baseURL: baseURL,
client: httpClient,
baseURL: baseURL,
subdomain: subdomain,

cachedResponse: nil,
cachedTenantID: "",
cachedResponseTime: time.Time{},
cachedResponseMutex: sync.Mutex{},
}

return client
Expand Down Expand Up @@ -93,17 +108,24 @@ type Services struct {
DiscoveryContext ServiceEndpoint
}

// DiscoverServices fetches from the service discovery service for a given subdomain
// DiscoverServices fetches from the service discovery service for the configured subdomain
// and parses the CyberArk Identity API URL and Inventory API URL.
// It also returns the Tenant ID UUID corresponding to the subdomain.
func (c *Client) DiscoverServices(ctx context.Context, subdomain string) (*Services, string, error) {
func (c *Client) DiscoverServices(ctx context.Context) (*Services, string, error) {
c.cachedResponseMutex.Lock()
defer c.cachedResponseMutex.Unlock()

if c.cachedResponse != nil && time.Since(c.cachedResponseTime) < 1*time.Hour {
return c.cachedResponse, c.cachedTenantID, nil
}

u, err := url.Parse(c.baseURL)
if err != nil {
return nil, "", fmt.Errorf("invalid base URL for service discovery: %w", err)
}

u.Path = path.Join(u.Path, "api/public/tenant-discovery")
u.RawQuery = url.Values{"bySubdomain": []string{subdomain}}.Encode()
u.RawQuery = url.Values{"bySubdomain": []string{c.subdomain}}.Encode()

endpoint := u.String()

Expand All @@ -127,7 +149,7 @@ func (c *Client) DiscoverServices(ctx context.Context, subdomain string) (*Servi
// a 404 error is returned with an empty JSON body "{}" if the subdomain is unknown; at the time of writing, we haven't observed
// any other errors and so we can't special case them
if resp.StatusCode == http.StatusNotFound {
return nil, "", fmt.Errorf("got an HTTP 404 response from service discovery; maybe the subdomain %q is incorrect or does not exist?", subdomain)
return nil, "", fmt.Errorf("got an HTTP 404 response from service discovery; maybe the subdomain %q is incorrect or does not exist?", c.subdomain)
}

return nil, "", fmt.Errorf("got unexpected status code %s from request to service discovery API", resp.Status)
Expand Down Expand Up @@ -167,8 +189,14 @@ func (c *Client) DiscoverServices(ctx context.Context, subdomain string) (*Servi
}
//TODO: Should add a check for discoveryContextAPI too?

return &Services{
services := &Services{
Identity: ServiceEndpoint{API: identityAPI},
DiscoveryContext: ServiceEndpoint{API: discoveryContextAPI},
}, discoveryResp.TenantID, nil
}

c.cachedResponse = services
c.cachedTenantID = discoveryResp.TenantID
c.cachedResponseTime = time.Now()

return services, discoveryResp.TenantID, nil
}
4 changes: 2 additions & 2 deletions internal/cyberark/servicediscovery/discovery_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,9 @@ func Test_DiscoverIdentityAPIURL(t *testing.T) {
},
})

client := New(httpClient)
client := New(httpClient, testSpec.subdomain)

services, _, err := client.DiscoverServices(ctx, testSpec.subdomain)
services, _, err := client.DiscoverServices(ctx)
if testSpec.expectedError != nil {
assert.EqualError(t, err, testSpec.expectedError.Error())
assert.Nil(t, services)
Expand Down
Loading