up
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Concelier Attestation Tests / attestation-tests (push) Has been cancelled
Export Center CI / export-ci (push) Has been cancelled
Notify Smoke Test / Notify Unit Tests (push) Has been cancelled
Notify Smoke Test / Notifier Service Tests (push) Has been cancelled
Notify Smoke Test / Notification Smoke Test (push) Has been cancelled
Policy Lint & Smoke / policy-lint (push) Has been cancelled
Scanner Analyzers / Discover Analyzers (push) Has been cancelled
Scanner Analyzers / Build Analyzers (push) Has been cancelled
Scanner Analyzers / Test Language Analyzers (push) Has been cancelled
Scanner Analyzers / Validate Test Fixtures (push) Has been cancelled
Scanner Analyzers / Verify Deterministic Output (push) Has been cancelled
Signals CI & Image / signals-ci (push) Has been cancelled
Signals Reachability Scoring & Events / reachability-smoke (push) Has been cancelled
Signals Reachability Scoring & Events / sign-and-upload (push) Has been cancelled
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Concelier Attestation Tests / attestation-tests (push) Has been cancelled
Export Center CI / export-ci (push) Has been cancelled
Notify Smoke Test / Notify Unit Tests (push) Has been cancelled
Notify Smoke Test / Notifier Service Tests (push) Has been cancelled
Notify Smoke Test / Notification Smoke Test (push) Has been cancelled
Policy Lint & Smoke / policy-lint (push) Has been cancelled
Scanner Analyzers / Discover Analyzers (push) Has been cancelled
Scanner Analyzers / Build Analyzers (push) Has been cancelled
Scanner Analyzers / Test Language Analyzers (push) Has been cancelled
Scanner Analyzers / Validate Test Fixtures (push) Has been cancelled
Scanner Analyzers / Verify Deterministic Output (push) Has been cancelled
Signals CI & Image / signals-ci (push) Has been cancelled
Signals Reachability Scoring & Events / reachability-smoke (push) Has been cancelled
Signals Reachability Scoring & Events / sign-and-upload (push) Has been cancelled
This commit is contained in:
@@ -1,93 +1,93 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace StellaOps.Registry.TokenService;
|
||||
|
||||
public static class RegistryScopeParser
|
||||
{
|
||||
public static IReadOnlyList<RegistryAccessRequest> Parse(IQueryCollection query)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(query);
|
||||
|
||||
var scopes = new List<string>();
|
||||
|
||||
if (query.TryGetValue("scope", out var scopeValues))
|
||||
{
|
||||
foreach (var scope in scopeValues)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(scope))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Support space-delimited scopes per OAuth2 spec
|
||||
foreach (var component in scope.Split(' ', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries))
|
||||
{
|
||||
scopes.Add(component);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var requests = new List<RegistryAccessRequest>(scopes.Count);
|
||||
foreach (var scope in scopes)
|
||||
{
|
||||
var request = ParseScope(scope);
|
||||
requests.Add(request);
|
||||
}
|
||||
|
||||
return requests;
|
||||
}
|
||||
|
||||
private static RegistryAccessRequest ParseScope(string scope)
|
||||
{
|
||||
var segments = scope.Split(':', StringSplitOptions.TrimEntries);
|
||||
if (segments.Length < 1)
|
||||
{
|
||||
throw new InvalidScopeException(scope, "scope missing resource type");
|
||||
}
|
||||
|
||||
var type = segments[0];
|
||||
if (!string.Equals(type, "repository", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
throw new InvalidScopeException(scope, $"unsupported resource type '{type}'");
|
||||
}
|
||||
|
||||
if (segments.Length < 2 || string.IsNullOrWhiteSpace(segments[1]))
|
||||
{
|
||||
throw new InvalidScopeException(scope, "repository scope missing name");
|
||||
}
|
||||
|
||||
var name = segments[1];
|
||||
var actions = segments.Length >= 3 && !string.IsNullOrWhiteSpace(segments[2])
|
||||
? segments[2].Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
|
||||
: Array.Empty<string>();
|
||||
|
||||
if (actions.Length == 0)
|
||||
{
|
||||
actions = new[] { "pull" };
|
||||
}
|
||||
|
||||
var normalized = actions
|
||||
.Select(action => action.ToLowerInvariant())
|
||||
.Distinct(StringComparer.OrdinalIgnoreCase)
|
||||
.ToArray();
|
||||
|
||||
return new RegistryAccessRequest(type.ToLowerInvariant(), name, normalized);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class InvalidScopeException : Exception
|
||||
{
|
||||
public InvalidScopeException(string scope, string reason)
|
||||
: base($"Invalid scope '{scope}': {reason}")
|
||||
{
|
||||
Scope = scope;
|
||||
Reason = reason;
|
||||
}
|
||||
|
||||
public string Scope { get; }
|
||||
|
||||
public string Reason { get; }
|
||||
}
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace StellaOps.Registry.TokenService;
|
||||
|
||||
public static class RegistryScopeParser
|
||||
{
|
||||
public static IReadOnlyList<RegistryAccessRequest> Parse(IQueryCollection query)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(query);
|
||||
|
||||
var scopes = new List<string>();
|
||||
|
||||
if (query.TryGetValue("scope", out var scopeValues))
|
||||
{
|
||||
foreach (var scope in scopeValues)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(scope))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Support space-delimited scopes per OAuth2 spec
|
||||
foreach (var component in scope.Split(' ', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries))
|
||||
{
|
||||
scopes.Add(component);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var requests = new List<RegistryAccessRequest>(scopes.Count);
|
||||
foreach (var scope in scopes)
|
||||
{
|
||||
var request = ParseScope(scope);
|
||||
requests.Add(request);
|
||||
}
|
||||
|
||||
return requests;
|
||||
}
|
||||
|
||||
private static RegistryAccessRequest ParseScope(string scope)
|
||||
{
|
||||
var segments = scope.Split(':', StringSplitOptions.TrimEntries);
|
||||
if (segments.Length < 1)
|
||||
{
|
||||
throw new InvalidScopeException(scope, "scope missing resource type");
|
||||
}
|
||||
|
||||
var type = segments[0];
|
||||
if (!string.Equals(type, "repository", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
throw new InvalidScopeException(scope, $"unsupported resource type '{type}'");
|
||||
}
|
||||
|
||||
if (segments.Length < 2 || string.IsNullOrWhiteSpace(segments[1]))
|
||||
{
|
||||
throw new InvalidScopeException(scope, "repository scope missing name");
|
||||
}
|
||||
|
||||
var name = segments[1];
|
||||
var actions = segments.Length >= 3 && !string.IsNullOrWhiteSpace(segments[2])
|
||||
? segments[2].Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
|
||||
: Array.Empty<string>();
|
||||
|
||||
if (actions.Length == 0)
|
||||
{
|
||||
actions = new[] { "pull" };
|
||||
}
|
||||
|
||||
var normalized = actions
|
||||
.Select(action => action.ToLowerInvariant())
|
||||
.Distinct(StringComparer.OrdinalIgnoreCase)
|
||||
.ToArray();
|
||||
|
||||
return new RegistryAccessRequest(type.ToLowerInvariant(), name, normalized);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class InvalidScopeException : Exception
|
||||
{
|
||||
public InvalidScopeException(string scope, string reason)
|
||||
: base($"Invalid scope '{scope}': {reason}")
|
||||
{
|
||||
Scope = scope;
|
||||
Reason = reason;
|
||||
}
|
||||
|
||||
public string Scope { get; }
|
||||
|
||||
public string Reason { get; }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user