in smoke/IotEdgeQuickstart/details/IotedgedLinux.cs [349:555]
public async Task Configure(
DeviceProvisioningMethod method,
Option<string> agentImage,
string hostname,
Option<string> parentHostname,
string deviceCaCert,
string deviceCaPk,
string deviceCaCerts,
LogLevel runtimeLogLevel)
{
agentImage.ForEach(
image =>
{
Console.WriteLine($"Setting up aziot-edged with agent image {image}");
},
() =>
{
Console.WriteLine("Setting up aziot-edged with agent image 1.0");
});
// Initialize each service's config file.
Dictionary<string, Config> config = new Dictionary<string, Config>();
config.Add(KEYD, await InitConfig(KEYD + ".default", "aziotks"));
config.Add(CERTD, await InitConfig(CERTD + ".default", "aziotcs"));
config.Add(IDENTITYD, await InitConfig(IDENTITYD + ".default", "aziotid"));
config.Add(EDGED, await InitConfig(EDGED + ".default", "iotedge"));
// Directory for storing keys; create it if it doesn't exist.
string keyDir = "/var/secrets/aziot/keyd/";
Directory.CreateDirectory(keyDir);
SetOwner(keyDir, config[KEYD].Owner, "700");
// Need to always reprovision so previous test runs don't affect this one.
config[EDGED].Document.ReplaceOrAdd("auto_reprovisioning_mode", "AlwaysOnStartup");
config[IDENTITYD].Document.RemoveIfExists("provisioning");
parentHostname.ForEach(
parent_hostame =>
config[IDENTITYD].Document.ReplaceOrAdd("provisioning.local_gateway_hostname", parent_hostame));
method.ManualConnectionString.Match(
cs =>
{
string keyPath = Path.Combine(keyDir, "device-id");
config[IDENTITYD].Document.ReplaceOrAdd("provisioning.source", "manual");
config[IDENTITYD].Document.ReplaceOrAdd("provisioning.authentication.method", "sas");
config[IDENTITYD].Document.ReplaceOrAdd("provisioning.authentication.device_id_pk", "device-id");
config[KEYD].Document.ReplaceOrAdd("preloaded_keys.device-id", $"file://{keyPath}");
string[] segments = cs.Split(";");
foreach (string s in segments)
{
string[] param = s.Split("=", 2);
switch (param[0])
{
case "HostName":
// replace IoTHub hostname with parent hostname for nested edge
config[IDENTITYD].Document.ReplaceOrAdd("provisioning.iothub_hostname", param[1]);
break;
case "SharedAccessKey":
File.WriteAllBytes(keyPath, Convert.FromBase64String(param[1]));
SetOwner(keyPath, config[KEYD].Owner, "600");
break;
case "DeviceId":
config[IDENTITYD].Document.ReplaceOrAdd("provisioning.device_id", param[1]);
break;
default:
break;
}
}
this.SetAuth("device-id", config);
return string.Empty;
},
() =>
{
config[IDENTITYD].Document.RemoveIfExists("provisioning");
return string.Empty;
});
method.Dps.ForEach(
dps =>
{
config[IDENTITYD].Document.ReplaceOrAdd("provisioning.source", "dps");
config[IDENTITYD].Document.ReplaceOrAdd("provisioning.global_endpoint", dps.EndPoint);
config[IDENTITYD].Document.ReplaceOrAdd("provisioning.scope_id", dps.ScopeId);
switch (dps.AttestationType)
{
case DPSAttestationType.SymmetricKey:
string dpsKeyPath = Path.Combine(keyDir, "device-id");
string dpsKey = dps.SymmetricKey.Expect(() => new ArgumentException("Expected symmetric key"));
File.WriteAllBytes(dpsKeyPath, Convert.FromBase64String(dpsKey));
SetOwner(dpsKeyPath, config[KEYD].Owner, "600");
config[KEYD].Document.ReplaceOrAdd("preloaded_keys.device-id", new Uri(dpsKeyPath).AbsoluteUri);
config[IDENTITYD].Document.ReplaceOrAdd("provisioning.attestation.method", "symmetric_key");
config[IDENTITYD].Document.ReplaceOrAdd("provisioning.attestation.symmetric_key", "device-id");
this.SetAuth("device-id", config);
break;
case DPSAttestationType.X509:
string certPath = dps.DeviceIdentityCertificate.Expect(() => new ArgumentException("Expected path to identity certificate"));
string keyPath = dps.DeviceIdentityPrivateKey.Expect(() => new ArgumentException("Expected path to identity private key"));
SetOwner(certPath, config[CERTD].Owner, "444");
SetOwner(keyPath, config[KEYD].Owner, "400");
config[CERTD].Document.ReplaceOrAdd("preloaded_certs.device-id", new Uri(certPath).AbsoluteUri);
config[KEYD].Document.ReplaceOrAdd("preloaded_keys.device-id", new Uri(keyPath).AbsoluteUri);
config[IDENTITYD].Document.ReplaceOrAdd("provisioning.attestation.method", "x509");
config[IDENTITYD].Document.ReplaceOrAdd("provisioning.attestation.identity_cert", "device-id");
config[IDENTITYD].Document.ReplaceOrAdd("provisioning.attestation.identity_pk", "device-id");
this.SetAuth("device-id", config);
break;
default:
break;
}
dps.RegistrationId.ForEach(id => { config[IDENTITYD].Document.ReplaceOrAdd("provisioning.attestation.registration_id", id); });
});
agentImage.ForEach(image =>
{
config[EDGED].Document.ReplaceOrAdd("agent.config.image", image);
});
config[EDGED].Document.ReplaceOrAdd("hostname", hostname);
config[IDENTITYD].Document.ReplaceOrAdd("hostname", hostname);
parentHostname.ForEach(v => config[EDGED].Document.ReplaceOrAdd("parent_hostname", v));
foreach (RegistryCredentials c in this.credentials)
{
config[EDGED].Document.ReplaceOrAdd("agent.config.auth.serveraddress", c.Address);
config[EDGED].Document.ReplaceOrAdd("agent.config.auth.username", c.User);
config[EDGED].Document.ReplaceOrAdd("agent.config.auth.password", c.Password);
}
config[EDGED].Document.ReplaceOrAdd("agent.env.RuntimeLogLevel", runtimeLogLevel.ToString());
if (this.httpUris.HasValue)
{
HttpUris uris = this.httpUris.OrDefault();
config[EDGED].Document.ReplaceOrAdd("connect.management_uri", uris.ConnectManagement);
config[EDGED].Document.ReplaceOrAdd("connect.workload_uri", uris.ConnectWorkload);
config[EDGED].Document.ReplaceOrAdd("listen.management_uri", uris.ListenManagement);
config[EDGED].Document.ReplaceOrAdd("listen.workload_uri", uris.ListenWorkload);
}
else
{
UriSocks socks = this.uriSocks;
config[EDGED].Document.ReplaceOrAdd("connect.management_uri", socks.ConnectManagement);
config[EDGED].Document.ReplaceOrAdd("connect.workload_uri", socks.ConnectWorkload);
config[EDGED].Document.ReplaceOrAdd("listen.management_uri", socks.ListenManagement);
config[EDGED].Document.ReplaceOrAdd("listen.workload_uri", socks.ListenWorkload);
}
foreach (string file in new string[] { deviceCaCert, deviceCaPk, deviceCaCerts })
{
if (string.IsNullOrEmpty(file))
{
throw new ArgumentException("device_ca_cert, device_ca_pk, and trusted_ca_certs must all be provided.");
}
if (!File.Exists(file))
{
throw new ArgumentException($"{file} does not exist.");
}
}
// Files must be readable by KS and CS users.
SetOwner(deviceCaCerts, config[CERTD].Owner, "444");
SetOwner(deviceCaCert, config[CERTD].Owner, "444");
SetOwner(deviceCaPk, config[KEYD].Owner, "400");
config[CERTD].Document.ReplaceOrAdd("preloaded_certs.aziot-edged-trust-bundle", new Uri(deviceCaCerts).AbsoluteUri);
config[CERTD].Document.ReplaceOrAdd("preloaded_certs.aziot-edged-ca", new Uri(deviceCaCert).AbsoluteUri);
config[KEYD].Document.ReplaceOrAdd("preloaded_keys.aziot-edged-ca", new Uri(deviceCaPk).AbsoluteUri);
this.proxy.ForEach(proxy => config[EDGED].Document.ReplaceOrAdd("agent.env.https_proxy", proxy));
this.upstreamProtocol.ForEach(upstreamProtocol => config[EDGED].Document.ReplaceOrAdd("agent.env.UpstreamProtocol", upstreamProtocol.ToString()));
foreach (KeyValuePair<string, Config> service in config)
{
string path = service.Key;
string text = service.Value.Document.ToString();
await File.WriteAllTextAsync(path, text);
SetOwner(path, service.Value.Owner, "644");
Console.WriteLine($"Created config {path}");
}
using (var cts = new CancellationTokenSource(TimeSpan.FromMinutes(2)))
{
Console.WriteLine($"Calling iotedge system set-log-level {runtimeLogLevel.ToString().ToLower()}");
string[] output = await Process.RunAsync("iotedge", $"system set-log-level {runtimeLogLevel.ToString().ToLower()}", cts.Token);
Console.WriteLine($"{output.ToString()}");
}
}