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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
//! An open-source project that aims to manage Redshift database roles and privileges in GitOps style, written in Rust.
//!
//! [**Home**](https://github.com/duyet/grant.rs) | [**Documentation**](https://docs.rs/grant)
//!
//! _This project is still in the early stages of development and is not ready for any kind of production use or any alpha/beta testing._
//!
//! # Usage
//!
//! Install binary from crates.io
//!
//! ```bash
//! cargo install grant
//! ```
//!
//! Using `grant` tool:
//!
//! ```bash
//! $ grant --help
//!
//! grant 0.0.1-beta.3
//! Manage database roles and privileges in GitOps style
//!
//! USAGE:
//!     grant <SUBCOMMAND>
//!
//! FLAGS:
//!     -h, --help       Prints help information
//!     -V, --version    Prints version information
//!
//! SUBCOMMANDS:
//!     apply       Apply a configuration to a redshift by file name. Yaml format are accepted
//!     gen         Generate sample configuration file
//!     gen-pass    Generate random password
//!     help        Prints this message or the help of the given subcommand(s)
//!     inspect     Inspect current database cluster with connection info from configuration file
//!     validate    Validate a configuration file or a target directory that contains configuration files
//! ```
//!
//! ## Generate project structure
//!
//! ```bash
//! grant gen --target ./cluster
//!
//! Creating path: "./cluster"
//! Generated: "./cluster/config.yml"
//! ```
//!
//! ## Apply privilege changes
//!
//! Content of `./examples/example.yaml`:
//!
//! ```yaml
//! connection:
//!   type: "postgres"
//!   # support environment variables, e.g. postgres://${HOSTNAME}:5432
//!   url: "postgres://postgres@localhost:5432/postgres"
//!
//! roles:
//!   - name: role_database_level
//!     type: database
//!     grants:
//!       - CREATE
//!       - TEMP
//!     databases:
//!       - postgres
//!
//!   - name: role_schema_level
//!     type: schema
//!     grants:
//!       - CREATE
//!     databases:
//!       - postgres
//!     schemas:
//!       - public
//!   - name: role_all_schema
//!     type: table
//!     grants:
//!       - SELECT
//!       - INSERT
//!       - UPDATE
//!     databases:
//!       - postgres
//!     schemas:
//!       - public
//!     tables:
//!       - ALL # include all table
//!       - +public_table # can add `+` to mark included tables
//!       - -secret_table # add `-` to exclude this table
//!
//! users:
//!   - name: duyet
//!     password: 1234567890 # password in plaintext
//!     roles:
//!       - role_database_level
//!       - role_all_schema
//!       - role_schema_level
//!   - name: duyet2
//!     password: md58243e8f5dfb84bbd851de920e28f596f # support md5 style: grant gen-pass -u duyet2
//!     roles:
//!       - role_database_level
//!       - role_all_schema
//!       - role_schema_level
//! ```
//!
//! Apply this config to cluster:
//!
//! ```bash
//! grant apply -f ./examples/example.yaml
//!
//! [2021-12-06T14:37:03Z INFO  grant::connection] Connected to database: postgres://postgres@localhost:5432/postgres
//! [2021-12-06T14:37:03Z INFO  grant::apply] Summary:
//!     ┌────────────┬────────────────────────────┐
//!     │ User       │ Action                     │
//!     │ ---        │ ---                        │
//!     │ duyet      │ no action (already exists) │
//!     │ duyet2     │ no action (already exists) │
//!     └────────────┴────────────────────────────┘
//! [2021-12-12T13:48:22Z INFO  grant::apply] Success: GRANT CREATE, TEMP ON DATABASE postgres TO duyet;
//! [2021-12-12T13:48:22Z INFO  grant::apply] Success: GRANT CREATE ON SCHEMA public TO duyet;
//! [2021-12-12T13:48:22Z INFO  grant::apply] Success: GRANT SELECT, INSERT, UPDATE ON ALL TABLES IN SCHEMA public TO duyet;
//! [2021-12-12T13:48:22Z INFO  grant::apply] Success: GRANT CREATE, TEMP ON DATABASE postgres TO duyet2;
//! [2021-12-12T13:48:22Z INFO  grant::apply] Success: GRANT CREATE ON SCHEMA public TO duyet2;
//! [2021-12-12T13:48:22Z INFO  grant::apply] Success: GRANT SELECT, INSERT, UPDATE ON ALL TABLES IN SCHEMA public TO duyet2;
//! [2021-12-12T13:48:22Z INFO  grant::apply] Summary:
//!     ┌────────┬─────────────────────┬──────────────────────┬─────────┐
//!     │ User   │ Role Name           │ Detail               │ Status  │
//!     │ ---    │ ---                 │ ---                  │ ---     │
//!     │ duyet  │ role_database_level │ database["postgres"] │ updated │
//!     │ duyet  │ role_schema_level   │ schema["public"]     │ updated │
//!     │ duyet  │ role_table_level    │ table["ALL"]         │ updated │
//!     │ duyet2 │ role_database_level │ database["postgres"] │ updated │
//!     │ duyet2 │ role_schema_level   │ schema["public"]     │ updated │
//!     │ duyet2 │ role_table_level    │ table["ALL"]         │ updated │
//!     └────────┴─────────────────────┴──────────────────────┴─────────┘
//! ```
//!
//! ## Generate random password
//!
//! ```bash
//! $ grant gen-pass
//!
//! Generated password: q)ItTjN$EXlkF@Tl
//! ```
//!
//! ```bash
//! $ grant gen-pass --user duyet
//!
//! Generated password: o^b3aD1L$xLm%#~U
//! Generated MD5 (user: duyet): md58243e8f5dfb84bbd851de920e28f596f
//! ```
//!
//! ## Inspect the current cluster
//!
//! ```bash
//! $ grant inspect -f examples/example.yaml
//!
//! [2021-11-29T07:46:44Z INFO  grant::inspect] Current users in postgres://postgres@localhost:5432/postgres:
//!     ┌────────────┬──────────┬───────┬──────────┐
//!     │ User       │ CreateDB │ Super │ Password │
//!     │ ---        │ ---      │ ---   │ ---      │
//!     │ postgres   │ true     │ true  │ ******** │
//!     │ duyet      │ false    │ false │ ******** │
//!     └────────────┴──────────┴───────┴──────────┘
//! ```
//!
//! # Developement
//!
//! Clone the repo:
//!
//! ```bash
//! git clone https://github.com/duyet/grant.rs && cd grant.rs
//! ```
//!
//! Postgres is required for testing, you might need to use the `docker-compose.yaml`:
//!
//! ```bash
//! docker-compose up -d
//! ```
//!
//! Make sure you have connection to `postgres://postgres:postgres@localhost:5432/postgres`.
//!
//! On the MacOS, the easiest way is install [Postgres.app](https://postgresapp.com).
//!
//! To run the unittest:
//!
//! ```bash
//! cargo test
//! ```
//!
//! # TODO
//!
//! - [x] Support reading connection info from environment variables
//! - [ ] Support store encrypted password in Git
//! - [x] Support Postgres and Redshift
//! - [ ] Support change password
//! - [ ] Visuallization (who can see what?)
//! - [ ] Apply show more detail about diff changes
//! - [ ] Inspect show more detail about user privileges
//!
//! # LICENSE
//!
//! MIT

pub mod apply;
pub mod cli;
pub mod config;
pub mod connection;
pub mod gen;
pub mod inspect;
pub mod validate;

pub use cli::Cli;
pub use config::Config;
pub use connection::DbConnection;

pub use apply::*;
pub use gen::*;
pub use inspect::*;
pub use validate::*;