Add PHP Analyzer Plugin and Composer Lock Data Handling
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
- Implemented the PhpAnalyzerPlugin to analyze PHP projects. - Created ComposerLockData class to represent data from composer.lock files. - Developed ComposerLockReader to load and parse composer.lock files asynchronously. - Introduced ComposerPackage class to encapsulate package details. - Added PhpPackage class to represent PHP packages with metadata and evidence. - Implemented PhpPackageCollector to gather packages from ComposerLockData. - Created PhpLanguageAnalyzer to perform analysis and emit results. - Added capability signals for known PHP frameworks and CMS. - Developed unit tests for the PHP language analyzer and its components. - Included sample composer.lock and expected output for testing. - Updated project files for the new PHP analyzer library and tests.
This commit is contained in:
@@ -1,15 +1,21 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
using Microsoft.Extensions.Options;
|
||||
using StellaOps.Scanner.Surface.Env;
|
||||
using StellaOps.Scanner.Surface.FS;
|
||||
using StellaOps.Scanner.Surface.Secrets;
|
||||
using StellaOps.Zastava.Core.Configuration;
|
||||
using StellaOps.Zastava.Observer.Backend;
|
||||
using StellaOps.Zastava.Observer.Configuration;
|
||||
using StellaOps.Zastava.Observer.ContainerRuntime.Cri;
|
||||
using StellaOps.Zastava.Observer.ContainerRuntime;
|
||||
using StellaOps.Zastava.Observer.ContainerRuntime.Cri;
|
||||
using StellaOps.Zastava.Observer.Posture;
|
||||
using StellaOps.Zastava.Observer.Runtime;
|
||||
using StellaOps.Zastava.Observer.Secrets;
|
||||
using StellaOps.Zastava.Observer.Surface;
|
||||
using StellaOps.Zastava.Observer.Worker;
|
||||
using StellaOps.Zastava.Observer.Backend;
|
||||
|
||||
namespace Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
@@ -83,6 +89,35 @@ public static class ObserverServiceCollectionExtensions
|
||||
|
||||
services.TryAddEnumerable(ServiceDescriptor.Singleton<IPostConfigureOptions<ZastavaRuntimeOptions>, ObserverRuntimeOptionsPostConfigure>());
|
||||
|
||||
// Surface environment + cache/manifest/secrets wiring
|
||||
services.AddSurfaceEnvironment(options =>
|
||||
{
|
||||
options.ComponentName = "Zastava.Observer";
|
||||
options.AddPrefix("ZASTAVA_OBSERVER");
|
||||
options.AddPrefix("ZASTAVA");
|
||||
options.KnownFeatureFlags.Add("drift");
|
||||
options.KnownFeatureFlags.Add("prefetch");
|
||||
options.TenantResolver = sp => sp.GetRequiredService<IOptions<ZastavaRuntimeOptions>>().Value.Tenant;
|
||||
});
|
||||
|
||||
services.AddSurfaceFileCache();
|
||||
services.AddSurfaceManifestStore();
|
||||
services.AddSurfaceSecrets(options =>
|
||||
{
|
||||
options.ComponentName = "Zastava.Observer";
|
||||
options.RequiredSecretTypes.Add("cas-access");
|
||||
options.RequiredSecretTypes.Add("attestation");
|
||||
});
|
||||
|
||||
services.TryAddSingleton(sp => sp.GetRequiredService<ISurfaceEnvironment>().Settings);
|
||||
services.TryAddEnumerable(ServiceDescriptor.Singleton<IConfigureOptions<SurfaceCacheOptions>>(sp =>
|
||||
new SurfaceCacheOptionsConfigurator(sp.GetRequiredService<SurfaceEnvironmentSettings>())));
|
||||
services.TryAddEnumerable(ServiceDescriptor.Singleton<IConfigureOptions<SurfaceManifestStoreOptions>>(sp =>
|
||||
new SurfaceManifestStoreOptionsConfigurator(sp.GetRequiredService<SurfaceEnvironmentSettings>())));
|
||||
|
||||
services.TryAddSingleton<IObserverSurfaceSecrets, ObserverSurfaceSecrets>();
|
||||
services.TryAddSingleton<IRuntimeSurfaceFsClient, RuntimeSurfaceFsClient>();
|
||||
|
||||
services.AddHostedService<ObserverBootstrapService>();
|
||||
services.AddHostedService<ContainerLifecycleHostedService>();
|
||||
services.AddHostedService<RuntimeEventDispatchService>();
|
||||
@@ -101,3 +136,34 @@ internal sealed class ObserverRuntimeOptionsPostConfigure : IPostConfigureOption
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class SurfaceCacheOptionsConfigurator : IConfigureOptions<SurfaceCacheOptions>
|
||||
{
|
||||
private readonly SurfaceEnvironmentSettings settings;
|
||||
|
||||
public SurfaceCacheOptionsConfigurator(SurfaceEnvironmentSettings settings)
|
||||
{
|
||||
this.settings = settings ?? throw new ArgumentNullException(nameof(settings));
|
||||
}
|
||||
|
||||
public void Configure(SurfaceCacheOptions options)
|
||||
{
|
||||
options.RootDirectory ??= settings.CacheRoot.FullName;
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class SurfaceManifestStoreOptionsConfigurator : IConfigureOptions<SurfaceManifestStoreOptions>
|
||||
{
|
||||
private readonly SurfaceEnvironmentSettings settings;
|
||||
|
||||
public SurfaceManifestStoreOptionsConfigurator(SurfaceEnvironmentSettings settings)
|
||||
{
|
||||
this.settings = settings ?? throw new ArgumentNullException(nameof(settings));
|
||||
}
|
||||
|
||||
public void Configure(SurfaceManifestStoreOptions options)
|
||||
{
|
||||
options.Bucket = string.IsNullOrWhiteSpace(settings.SurfaceFsBucket) ? options.Bucket : settings.SurfaceFsBucket;
|
||||
options.RootDirectory ??= Path.Combine(settings.CacheRoot.FullName, "manifests");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,9 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="../__Libraries/StellaOps.Zastava.Core/StellaOps.Zastava.Core.csproj" />
|
||||
<ProjectReference Include="../../Scanner/__Libraries/StellaOps.Scanner.Surface.Env/StellaOps.Scanner.Surface.Env.csproj" />
|
||||
<ProjectReference Include="../../Scanner/__Libraries/StellaOps.Scanner.Surface.FS/StellaOps.Scanner.Surface.FS.csproj" />
|
||||
<ProjectReference Include="../../Scanner/__Libraries/StellaOps.Scanner.Surface.Secrets/StellaOps.Scanner.Surface.Secrets.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Protobuf Include="Protos/runtime/v1/runtime.proto" GrpcServices="Client" />
|
||||
|
||||
@@ -19,14 +19,26 @@ internal sealed class RuntimeSurfaceFsClient : IRuntimeSurfaceFsClient
|
||||
_environment = environment ?? throw new ArgumentNullException(nameof(environment));
|
||||
}
|
||||
|
||||
public Task<SurfaceManifestDocument?> TryGetManifestAsync(string manifestDigest, CancellationToken cancellationToken = default)
|
||||
public async Task<SurfaceManifestDocument?> TryGetManifestAsync(string manifestDigest, CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(manifestDigest))
|
||||
{
|
||||
return Task.FromResult<SurfaceManifestDocument?>(null);
|
||||
return null;
|
||||
}
|
||||
|
||||
// manifest digests follow sha256:<hex>; manifest reader handles validation and tenant discovery
|
||||
return _manifestReader.TryGetByDigestAsync(manifestDigest.Trim(), cancellationToken);
|
||||
var manifest = await _manifestReader.TryGetByDigestAsync(manifestDigest.Trim(), cancellationToken).ConfigureAwait(false);
|
||||
if (manifest is null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// Enforce tenant scoping to avoid crossing cache boundaries in multi-tenant deployments.
|
||||
if (!string.IsNullOrWhiteSpace(manifest.Tenant)
|
||||
&& !string.Equals(manifest.Tenant, _environment.Tenant, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return manifest;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user