(t *testing.T)
| 593 | } |
| 594 | |
| 595 | func TestAIProvidersKeyManagement(t *testing.T) { |
| 596 | t.Parallel() |
| 597 | |
| 598 | t.Run("CreateWithKeysReturnsMasked", func(t *testing.T) { |
| 599 | t.Parallel() |
| 600 | client := coderdtest.New(t, nil) |
| 601 | _ = coderdtest.CreateFirstUser(t, client) |
| 602 | ctx := testutil.Context(t, testutil.WaitLong) |
| 603 | |
| 604 | const ( |
| 605 | primary = "sk-openai-primary-fixture-aaaaaa" //nolint:gosec // test fixture, not a real credential |
| 606 | secondary = "sk-openai-secondary-fixture-bbbbbb" //nolint:gosec // test fixture, not a real credential |
| 607 | ) |
| 608 | |
| 609 | //nolint:gocritic // Owner role is the audience for this endpoint. |
| 610 | provider, err := client.CreateAIProvider(ctx, codersdk.CreateAIProviderRequest{ |
| 611 | Type: codersdk.AIProviderTypeOpenAI, |
| 612 | Name: "keys-openai", |
| 613 | Enabled: true, |
| 614 | BaseURL: "https://api.openai.com/v1", |
| 615 | APIKeys: []string{primary, secondary}, |
| 616 | }) |
| 617 | require.NoError(t, err) |
| 618 | require.Len(t, provider.APIKeys, 2) |
| 619 | // Masked form preserves prefix and suffix while hiding the |
| 620 | // middle, so it's enough for an operator to recognize the key |
| 621 | // without recovering the plaintext. |
| 622 | require.True(t, strings.HasPrefix(provider.APIKeys[0].Masked, "sk-o")) |
| 623 | require.True(t, strings.HasSuffix(provider.APIKeys[0].Masked, "aaaa")) |
| 624 | require.NotContains(t, provider.APIKeys[0].Masked, primary) |
| 625 | require.NotContains(t, provider.APIKeys[1].Masked, secondary) |
| 626 | require.NotEqual(t, uuid.Nil, provider.APIKeys[0].ID) |
| 627 | require.NotEqual(t, uuid.Nil, provider.APIKeys[1].ID) |
| 628 | }) |
| 629 | |
| 630 | t.Run("ResponseHidesPlaintext", func(t *testing.T) { |
| 631 | t.Parallel() |
| 632 | client := coderdtest.New(t, nil) |
| 633 | _ = coderdtest.CreateFirstUser(t, client) |
| 634 | ctx := testutil.Context(t, testutil.WaitLong) |
| 635 | |
| 636 | const plaintext = "sk-openai-extra-secret-cccccccccccc" //nolint:gosec // test fixture, not a real credential |
| 637 | |
| 638 | //nolint:gocritic // Owner role is the audience for this endpoint. |
| 639 | _, err := client.CreateAIProvider(ctx, codersdk.CreateAIProviderRequest{ |
| 640 | Type: codersdk.AIProviderTypeOpenAI, |
| 641 | Name: "keys-secret", |
| 642 | Enabled: true, |
| 643 | BaseURL: "https://api.openai.com/v1", |
| 644 | APIKeys: []string{plaintext}, |
| 645 | }) |
| 646 | require.NoError(t, err) |
| 647 | |
| 648 | // Inspect the raw HTTP body of the GET response. The masked |
| 649 | // form must replace the plaintext entirely on the wire. |
| 650 | res, err := client.Request(ctx, http.MethodGet, "/api/v2/ai/providers/keys-secret", nil) |
| 651 | require.NoError(t, err) |
| 652 | defer res.Body.Close() |
nothing calls this directly
no test coverage detected