-
Notifications
You must be signed in to change notification settings - Fork 167
feat(feature-flags): add agentless configuration keys, settings, and endpoint derivation #9040
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
pavlokhrebto
wants to merge
7
commits into
master
from
pavlo.khrebto/EX-2703/ffe-config-and-endpoint
Open
Changes from 5 commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
e36d5f3
feat(feature-flags): add agentless configuration keys to supported-co…
pavlokhrebto 477c12c
feat(feature-flags): add FeatureFlagsSettings with source resolution …
pavlokhrebto b2c13cf
feat(feature-flags): add AgentlessEndpoint for CDN URL derivation
pavlokhrebto a148b58
test(feature-flags): add unit tests for FeatureFlagsSettings and Agen…
pavlokhrebto ac79e9b
fix(tests): correct AgentlessEndpointTests invalid URL expectations
pavlokhrebto e59f1d7
fix(feature-flags): redact agentless base URL telemetry and reject ma…
pavlokhrebto f142d9a
Merge branch 'master' of github.com:DataDog/dd-trace-dotnet into pavl…
pavlokhrebto File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
116 changes: 116 additions & 0 deletions
116
tracer/src/Datadog.Trace/FeatureFlags/Agentless/AgentlessEndpoint.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,116 @@ | ||
| // <copyright file="AgentlessEndpoint.cs" company="Datadog"> | ||
| // Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2 License. | ||
| // This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc. | ||
| // </copyright> | ||
|
|
||
| #nullable enable | ||
|
|
||
| using System; | ||
| using Datadog.Trace.Util; | ||
|
|
||
| namespace Datadog.Trace.FeatureFlags.Agentless; | ||
|
|
||
| /// <summary> | ||
| /// The agentless endpoint, derived from the Datadog site or a custom base URL. | ||
| /// </summary> | ||
| internal readonly struct AgentlessEndpoint | ||
| { | ||
| /// <summary> | ||
| /// Canonical rules-based server path, appended to the managed CDN host and to custom base | ||
| /// URLs that only supply an origin. | ||
| /// </summary> | ||
| internal const string DefaultPath = "/api/v2/feature-flagging/config/rules-based/server"; | ||
|
|
||
| /// <summary> | ||
| /// The prefix prepended to the site to form the managed CDN host. | ||
| /// </summary> | ||
| internal const string ManagedHostPrefix = "ufc-server.ff-cdn."; | ||
|
|
||
| private AgentlessEndpoint(Uri uri, bool isManaged) | ||
| { | ||
| Uri = uri; | ||
| IsManaged = isManaged; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Gets the endpoint URI. | ||
| /// </summary> | ||
| public Uri Uri { get; } | ||
|
|
||
| /// <summary> | ||
| /// Gets a value indicating whether this is the endpoint derived from the site. The API key is | ||
| /// only sent there: a custom endpoint reports its own authentication failure rather than | ||
| /// having the credential guessed onto it. | ||
| /// </summary> | ||
| public bool IsManaged { get; } | ||
|
|
||
| /// <summary> | ||
| /// Builds the endpoint. Without a custom <paramref name="baseUrl"/> the managed Datadog CDN | ||
| /// endpoint is derived from the (lowercased) site, so staging and government sites resolve | ||
| /// with no allowlist, and <c>dd_env</c> is added only when an environment is configured. | ||
| /// A custom base URL that is an origin receives the canonical path; one that carries a path | ||
| /// is used verbatim. | ||
| /// </summary> | ||
| /// <param name="site">The Datadog site, for example <c>datadoghq.com</c>.</param> | ||
| /// <param name="env">The configured environment, or <c>null</c>.</param> | ||
| /// <param name="baseUrl">The configured endpoint override, or <c>null</c>.</param> | ||
| /// <param name="endpoint">The resulting endpoint.</param> | ||
| /// <param name="error">Why the configured base URL was rejected. Never contains the URL, which may carry credentials.</param> | ||
| /// <returns><c>true</c> when an endpoint could be built.</returns> | ||
| public static bool TryCreate(string? site, string? env, string? baseUrl, out AgentlessEndpoint endpoint, out string? error) | ||
| { | ||
| endpoint = default; | ||
| error = null; | ||
|
|
||
| var configured = baseUrl?.Trim(); | ||
| if (StringUtil.IsNullOrEmpty(configured)) | ||
| { | ||
| var trimmedSite = site?.Trim(); | ||
| if (StringUtil.IsNullOrEmpty(trimmedSite)) | ||
| { | ||
| error = "No Datadog site is configured"; | ||
| return false; | ||
| } | ||
|
|
||
| var managed = new UriBuilder("https", ManagedHostPrefix + trimmedSite!.ToLowerInvariant()) { Path = DefaultPath }; | ||
| if (!StringUtil.IsNullOrEmpty(env)) | ||
| { | ||
| managed.Query = "dd_env=" + Uri.EscapeDataString(env!); | ||
| } | ||
|
|
||
| endpoint = new AgentlessEndpoint(managed.Uri, isManaged: true); | ||
| return true; | ||
| } | ||
|
|
||
| // A URL with internal whitespace is malformed, and Uri parsing is lenient enough to accept it. | ||
| foreach (var character in configured!) | ||
| { | ||
| if (char.IsWhiteSpace(character)) | ||
| { | ||
| error = "The configured Feature Flags agentless URL is not a valid URL"; | ||
| return false; | ||
| } | ||
| } | ||
|
|
||
| if (!Uri.TryCreate(configured, UriKind.Absolute, out var custom) || StringUtil.IsNullOrEmpty(custom.Host)) | ||
| { | ||
| error = "The configured Feature Flags agentless URL is not a valid absolute URL"; | ||
| return false; | ||
| } | ||
|
|
||
| // http is accepted for a custom endpoint only: pointing at one is an operator decision. | ||
| if (custom.Scheme != Uri.UriSchemeHttps && custom.Scheme != Uri.UriSchemeHttp) | ||
| { | ||
| error = "The configured Feature Flags agentless URL must use HTTP or HTTPS"; | ||
| return false; | ||
| } | ||
|
|
||
| if (custom.AbsolutePath is "" or "/") | ||
| { | ||
| custom = new UriBuilder(custom) { Path = DefaultPath }.Uri; | ||
| } | ||
|
|
||
| endpoint = new AgentlessEndpoint(custom, isManaged: false); | ||
| return true; | ||
| } | ||
| } | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.