Compare commits

..

2 Commits

Author SHA1 Message Date
be42b07086
add tls trust chain for AWS
All checks were successful
continuous-integration/drone/push Build is passing
2022-01-19 21:17:44 -08:00
8d6dcc2a13
update readme 2022-01-19 20:32:07 -08:00
6 changed files with 49 additions and 18 deletions

20
Amazon_Root_CA_1.pem Normal file
View File

@ -0,0 +1,20 @@
-----BEGIN CERTIFICATE-----
MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF
ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6
b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL
MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv
b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj
ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM
9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw
IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6
VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L
93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm
jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA
A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI
U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs
N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv
o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU
5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy
rqXRfboQnoZsG4q5WTP468SQvvG5
-----END CERTIFICATE-----

View File

@ -11,19 +11,14 @@ tweaks in the signature calculation, which is planned for a zig version
(probably self-hosted 0.9.0) that no longer has an error triggered. Examples (probably self-hosted 0.9.0) that no longer has an error triggered. Examples
of usage are in src/main.zig. of usage are in src/main.zig.
This is designed to be built statically using the `aws_c_*` libraries, so Current executable size for the demo is 868k after compiling with -Drelease-safe
we inherit a lot of the goodness of the work going on there. Current and [stripping the executable after compilation](https://github.com/ziglang/zig/issues/351).
executable size is 9.7M, about half of which is due to the SSL library. This is for x86_linux, (which is all that's tested at the moment).
Running strip on the executable after compilation (it seems zig strip
only goes so far), reduces this to 4.3M. This is for x86_linux,
(which is all that's tested at the moment).
## Building ## Building
`zig build` should work. It will build the code generation project, run `zig build` should work. It will build the code generation project, run
the code generation, then build the main project with the generated code. the code generation, then build the main project with the generated code.
There is also a Makefile included, but this hasn't been used in a while
and I'm not sure that works at the moment.
First time build should use `zig build -Dfetch` to fetch dependent packages First time build should use `zig build -Dfetch` to fetch dependent packages
(zfetch and friends). (zfetch and friends).

View File

@ -53,6 +53,7 @@ pub fn build(b: *Builder) !void {
// so we'll have to keep that in sync with upstream // so we'll have to keep that in sync with upstream
// const zfetch = @import("libs/zfetch/build.zig"); // const zfetch = @import("libs/zfetch/build.zig");
exe.addPackage(getZfetchPackage(b, "libs/zfetch") catch unreachable); exe.addPackage(getZfetchPackage(b, "libs/zfetch") catch unreachable);
exe.addPackagePath("iguanaTLS", "libs/zfetch/libs/iguanaTLS/src/main.zig");
const run_cmd = exe.run(); const run_cmd = exe.run();
run_cmd.step.dependOn(b.getInstallStep()); run_cmd.step.dependOn(b.getInstallStep());

View File

@ -25,16 +25,19 @@ pub const services = servicemodel.services;
/// This will give you a constant with service data for sts, ec2, s3 and ddb only /// This will give you a constant with service data for sts, ec2, s3 and ddb only
pub const Services = servicemodel.Services; pub const Services = servicemodel.Services;
pub const ClientOptions = struct {
trust_pem: ?[]const u8 = awshttp.default_root_ca,
};
pub const Client = struct { pub const Client = struct {
allocator: std.mem.Allocator, allocator: std.mem.Allocator,
aws_http: awshttp.AwsHttp, aws_http: awshttp.AwsHttp,
const Self = @This(); const Self = @This();
pub fn init(allocator: std.mem.Allocator) Self { pub fn init(allocator: std.mem.Allocator, options: ClientOptions) !Self {
return .{ return Self{
.allocator = allocator, .allocator = allocator,
.aws_http = awshttp.AwsHttp.init(allocator), .aws_http = try awshttp.AwsHttp.init(allocator, options.trust_pem),
}; };
} }
pub fn deinit(self: *Client) void { pub fn deinit(self: *Client) void {

View File

@ -12,6 +12,7 @@ const base = @import("aws_http_base.zig");
const signing = @import("aws_signing.zig"); const signing = @import("aws_signing.zig");
const credentials = @import("aws_credentials.zig"); const credentials = @import("aws_credentials.zig");
const zfetch = @import("zfetch"); const zfetch = @import("zfetch");
const tls = @import("iguanaTLS");
const CN_NORTH_1_HASH = std.hash_map.hashString("cn-north-1"); const CN_NORTH_1_HASH = std.hash_map.hashString("cn-north-1");
const CN_NORTHWEST_1_HASH = std.hash_map.hashString("cn-northwest-1"); const CN_NORTHWEST_1_HASH = std.hash_map.hashString("cn-northwest-1");
@ -20,6 +21,10 @@ const US_ISOB_EAST_1_HASH = std.hash_map.hashString("us-isob-east-1");
const log = std.log.scoped(.awshttp); const log = std.log.scoped(.awshttp);
const amazon_root_ca_1 = @embedFile("../Amazon_Root_CA_1.pem");
pub const default_root_ca = amazon_root_ca_1;
pub const AwsError = error{ pub const AwsError = error{
AddHeaderError, AddHeaderError,
AlpnError, AlpnError,
@ -57,20 +62,29 @@ const EndPoint = struct {
self.allocator.free(self.uri); self.allocator.free(self.uri);
} }
}; };
pub const AwsHttp = struct { pub const AwsHttp = struct {
allocator: std.mem.Allocator, allocator: std.mem.Allocator,
trust_chain: ?tls.x509.CertificateChain,
const Self = @This(); const Self = @This();
pub fn init(allocator: std.mem.Allocator) Self { /// Recommend usage is init(allocator, awshttp.default_root_ca)
return .{ /// Passing null for root_pem will result in no TLS verification
pub fn init(allocator: std.mem.Allocator, root_pem: ?[]const u8) !Self {
var trust_chain: ?tls.x509.CertificateChain = null;
if (root_pem) |p| {
var fbs = std.io.fixedBufferStream(p);
trust_chain = try tls.x509.CertificateChain.from_pem(allocator, fbs.reader());
}
return Self{
.allocator = allocator, .allocator = allocator,
.trust_chain = trust_chain,
// .credentialsProvider = // creds provider could be useful // .credentialsProvider = // creds provider could be useful
}; };
} }
pub fn deinit(self: *AwsHttp) void { pub fn deinit(self: *AwsHttp) void {
if (self.trust_chain) |c| c.deinit();
_ = self; _ = self;
log.debug("Deinit complete", .{}); log.debug("Deinit complete", .{});
} }
@ -160,7 +174,7 @@ pub const AwsHttp = struct {
const url = try std.fmt.allocPrint(self.allocator, "{s}{s}", .{ endpoint.uri, request.path }); const url = try std.fmt.allocPrint(self.allocator, "{s}{s}", .{ endpoint.uri, request.path });
defer self.allocator.free(url); defer self.allocator.free(url);
log.debug("Request url: {s}", .{url}); log.debug("Request url: {s}", .{url});
var req = try zfetch.Request.init(self.allocator, url, null); var req = try zfetch.Request.init(self.allocator, url, self.trust_chain);
defer req.deinit(); defer req.deinit();
const method = std.meta.stringToEnum(zfetch.Method, request_cp.method).?; const method = std.meta.stringToEnum(zfetch.Method, request_cp.method).?;
@ -182,8 +196,6 @@ pub const AwsHttp = struct {
content_length = std.fmt.parseInt(usize, h.value, 10) catch 0; content_length = std.fmt.parseInt(usize, h.value, 10) catch 0;
} }
const reader = req.reader(); const reader = req.reader();
// TODO: Get content length and use that to allocate the buffer
// Content length can be missing, and why would we trust it anyway
var buf: [65535]u8 = undefined; var buf: [65535]u8 = undefined;
var resp_payload = try std.ArrayList(u8).initCapacity(self.allocator, content_length); var resp_payload = try std.ArrayList(u8).initCapacity(self.allocator, content_length);
defer resp_payload.deinit(); defer resp_payload.deinit();

View File

@ -71,7 +71,7 @@ pub fn main() anyerror!void {
} }
std.log.info("Start\n", .{}); std.log.info("Start\n", .{});
var client = aws.Client.init(allocator); var client = try aws.Client.init(allocator, .{});
const options = aws.Options{ const options = aws.Options{
.region = "us-west-2", .region = "us-west-2",
.client = client, .client = client,