-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathacl.zig
More file actions
executable file
·84 lines (68 loc) · 2.76 KB
/
Copy pathacl.zig
File metadata and controls
executable file
·84 lines (68 loc) · 2.76 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
const std = @import("std");
// 252 = SigV4 k_secret buffer (256) minus the 4-byte "AWS4" prefix.
pub const MAX_KEY_LEN: usize = 252;
pub const Role = enum {
Admin,
Reader,
Writer,
};
pub const Credential = struct {
access_key: []const u8,
secret_key: []const u8,
role: Role,
};
pub fn stringToRole(role_str: []const u8) !Role {
if (std.mem.eql(u8, role_str, "admin")) return .Admin;
if (std.mem.eql(u8, role_str, "reader")) return .Reader;
if (std.mem.eql(u8, role_str, "writer")) return .Writer;
return error.BadCredentialRole;
}
// Permission model:
// Admin : all methods
// Writer : read + write (GET, HEAD, OPTIONS, PUT, POST, DELETE)
// Reader : read-only (GET, HEAD, OPTIONS)
pub fn roleAllowsMethod(role: Role, method: []const u8) bool {
return switch (role) {
.Admin => true,
.Reader => std.mem.eql(u8, method, "GET") or
std.mem.eql(u8, method, "HEAD") or
std.mem.eql(u8, method, "OPTIONS"),
.Writer => std.mem.eql(u8, method, "GET") or
std.mem.eql(u8, method, "HEAD") or
std.mem.eql(u8, method, "OPTIONS") or
std.mem.eql(u8, method, "PUT") or
std.mem.eql(u8, method, "POST") or
std.mem.eql(u8, method, "DELETE"),
};
}
// Parse a single credential string: "role:access_key:secret_key".
// Note: secret_key cannot contain ':'.
pub fn parseCredential(cred_str: []const u8) !Credential {
var itr = std.mem.splitScalar(u8, cred_str, ':');
const role_str = itr.next() orelse return error.BadCredentialFormat;
const access_key = itr.next() orelse return error.BadCredentialFormat;
const secret_key = itr.next() orelse return error.BadCredentialFormat;
if (itr.next() != null) return error.BadCredentialFormat;
if (role_str.len == 0 or access_key.len == 0 or secret_key.len == 0)
return error.BadCredentialFormat;
if (access_key.len > MAX_KEY_LEN or secret_key.len > MAX_KEY_LEN)
return error.CredentialKeyTooLong;
return Credential{
.role = try stringToRole(role_str),
.access_key = access_key,
.secret_key = secret_key,
};
}
pub fn parseCredentials(allocator: std.mem.Allocator, input: []const u8) ![]Credential {
if (input.len == 0) return error.BadCredentialInputFormat;
var credentials = std.ArrayListUnmanaged(Credential){};
errdefer credentials.deinit(allocator);
var itr = std.mem.splitScalar(u8, input, ',');
while (itr.next()) |record| {
if (record.len == 0) return error.BadCredentialInputFormat;
const pc = try parseCredential(record);
try credentials.append(allocator, pc);
}
if (credentials.items.len == 0) return error.BadCredentialInputFormat;
return credentials.toOwnedSlice(allocator);
}