conjur-asset-ui-api 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. checksums.yaml +7 -0
  2. data/.git-hooks/pre_commit/ensure_livescript_compiled.rb +31 -0
  3. data/.git-hooks/pre_commit/trailing_whitespace.rb +26 -0
  4. data/.gitignore +20 -0
  5. data/.overcommit.yml +5 -0
  6. data/.project +18 -0
  7. data/Gemfile +8 -0
  8. data/LICENSE.txt +22 -0
  9. data/README.md +41 -0
  10. data/Rakefile +1 -0
  11. data/compile_ls +2 -0
  12. data/conjur-asset-ui.gemspec +36 -0
  13. data/lib/conjur-asset-ui-version.rb +7 -0
  14. data/lib/conjur-asset-ui.rb +7 -0
  15. data/lib/conjur/audit/follower.rb +63 -0
  16. data/lib/conjur/audit/humanizer.rb +53 -0
  17. data/lib/conjur/audit/tableizer.rb +55 -0
  18. data/lib/conjur/command/ui.rb +38 -0
  19. data/lib/conjur/webserver/api_proxy.rb +94 -0
  20. data/lib/conjur/webserver/audit_stream.rb +92 -0
  21. data/lib/conjur/webserver/authorize.rb +28 -0
  22. data/lib/conjur/webserver/conjur_info.rb +33 -0
  23. data/lib/conjur/webserver/home.rb +36 -0
  24. data/lib/conjur/webserver/login.rb +50 -0
  25. data/lib/conjur/webserver/server.rb +111 -0
  26. data/livescript/views/audit.ls +124 -0
  27. data/public/css/bootstrap.css +7 -0
  28. data/public/css/styles.less +400 -0
  29. data/public/fonts/glyphicons-halflings-regular.eot +0 -0
  30. data/public/fonts/glyphicons-halflings-regular.svg +229 -0
  31. data/public/fonts/glyphicons-halflings-regular.ttf +0 -0
  32. data/public/fonts/glyphicons-halflings-regular.woff +0 -0
  33. data/public/images/conjur-logo.svg +26 -0
  34. data/public/images/icon-client-pc.svg +12 -0
  35. data/public/images/icon-environment.png +0 -0
  36. data/public/images/icon-person.svg +12 -0
  37. data/public/images/icon-service-dots.svg +13 -0
  38. data/public/images/icon-variable.png +0 -0
  39. data/public/index.html +121 -0
  40. data/public/js/lib/JSXTransformer.js +10862 -0
  41. data/public/js/lib/async.js +958 -0
  42. data/public/js/lib/backbone.js +2 -0
  43. data/public/js/lib/bootstrap.js +6 -0
  44. data/public/js/lib/date.extensions.js +141 -0
  45. data/public/js/lib/less.js +16 -0
  46. data/public/js/lib/moment.js +7768 -0
  47. data/public/js/lib/pace.js +2 -0
  48. data/public/js/lib/prelude-browser-min.js +1 -0
  49. data/public/js/lib/react-with-addons.js +15505 -0
  50. data/public/js/lib/react.js +14469 -0
  51. data/public/js/lib/sorted-set.no-require.js +1170 -0
  52. data/public/js/lib/sorted-set.no-require.js.txt +6 -0
  53. data/public/js/lib/underscore-min.js +6 -0
  54. data/public/js/lib/underscore.string.min.js +1 -0
  55. data/public/js/main.js +353 -0
  56. data/public/js/models/namespace.js +6 -0
  57. data/public/js/models/policyList.js +10 -0
  58. data/public/js/models/record.js +26 -0
  59. data/public/js/models/resourceList.js +61 -0
  60. data/public/js/models/userList.js +16 -0
  61. data/public/js/models/variableList.js +12 -0
  62. data/public/js/views/audit.js +191 -0
  63. data/public/js/views/dashboard.js +35 -0
  64. data/public/js/views/generic.js +42 -0
  65. data/public/js/views/group.js +32 -0
  66. data/public/js/views/groups.js +18 -0
  67. data/public/js/views/host.js +40 -0
  68. data/public/js/views/hosts.js +18 -0
  69. data/public/js/views/layer.js +63 -0
  70. data/public/js/views/layers.js +18 -0
  71. data/public/js/views/mixins/search.js +9 -0
  72. data/public/js/views/namespaces.js +40 -0
  73. data/public/js/views/navSearch.js +16 -0
  74. data/public/js/views/permissions.js +91 -0
  75. data/public/js/views/policies.js +17 -0
  76. data/public/js/views/policy.js +23 -0
  77. data/public/js/views/resource.js +23 -0
  78. data/public/js/views/role.js +18 -0
  79. data/public/js/views/searchResults.js +146 -0
  80. data/public/js/views/time.js +14 -0
  81. data/public/js/views/user.js +22 -0
  82. data/public/js/views/users.js +18 -0
  83. data/public/js/views/variable.js +41 -0
  84. data/public/js/views/variables.js +18 -0
  85. data/vendor/prelude-ls/.gitignore +2 -0
  86. data/vendor/prelude-ls/.travis.yml +3 -0
  87. data/vendor/prelude-ls/CHANGELOG.md +81 -0
  88. data/vendor/prelude-ls/LICENSE +22 -0
  89. data/vendor/prelude-ls/Makefile +50 -0
  90. data/vendor/prelude-ls/README.md +15 -0
  91. data/vendor/prelude-ls/browser/prelude-browser-min.js +1 -0
  92. data/vendor/prelude-ls/browser/prelude-browser.js +1172 -0
  93. data/vendor/prelude-ls/lib/Func.js +40 -0
  94. data/vendor/prelude-ls/lib/List.js +602 -0
  95. data/vendor/prelude-ls/lib/Num.js +129 -0
  96. data/vendor/prelude-ls/lib/Obj.js +153 -0
  97. data/vendor/prelude-ls/lib/Str.js +68 -0
  98. data/vendor/prelude-ls/lib/index.js +164 -0
  99. data/vendor/prelude-ls/package.json +50 -0
  100. data/vendor/prelude-ls/package.ls +46 -0
  101. data/vendor/prelude-ls/src/Func.ls +17 -0
  102. data/vendor/prelude-ls/src/List.ls +299 -0
  103. data/vendor/prelude-ls/src/Num.ls +83 -0
  104. data/vendor/prelude-ls/src/Obj.ls +61 -0
  105. data/vendor/prelude-ls/src/Str.ls +32 -0
  106. data/vendor/prelude-ls/src/index.ls +56 -0
  107. data/vendor/prelude-ls/test/Func.ls +36 -0
  108. data/vendor/prelude-ls/test/List.ls +751 -0
  109. data/vendor/prelude-ls/test/Num.ls +258 -0
  110. data/vendor/prelude-ls/test/Obj.ls +145 -0
  111. data/vendor/prelude-ls/test/Prelude.ls +49 -0
  112. data/vendor/prelude-ls/test/Str.ls +208 -0
  113. data/vendor/prelude-ls/test/browser.html +5 -0
  114. metadata +328 -0
@@ -0,0 +1,16 @@
1
+ if (typeof $ === "undefined") { throw new Error("jQuery is required") }
2
+
3
+ var UserListModel = function(){
4
+ var options = {
5
+ namespaceSelector: function(member) {
6
+ var idTokens = member.id.split('@');
7
+ if ( idTokens.length > 1 ) {
8
+ return idTokens.slice(1, idTokens.length-1).join['@'];
9
+ }
10
+ else {
11
+ return null;
12
+ }
13
+ }
14
+ };
15
+ return ResourceListModel("user", options);
16
+ }
@@ -0,0 +1,12 @@
1
+ if (typeof $ === "undefined") { throw new Error("jQuery is required") }
2
+
3
+ var VariableListModel = function(){
4
+ var options = {
5
+ filter: function(member) {
6
+ var idTokens = member.id.split(':');
7
+ var id = idTokens[idTokens.length-1];
8
+ return id.split('/').length > 1;
9
+ }
10
+ };
11
+ return ResourceListModel("variable", options);
12
+ }
@@ -0,0 +1,191 @@
1
+ // Generated by LiveScript 1.2.0
2
+ (function(){
3
+ var ref$, table, div, th, tr, td, thead, tbody, section, h3, time, map, each, unique, isType, join, fields, AuditTableHeader, Timestamp, wrapArray, AuditEntry, newEventSet, AuditTable, GlobalAudit, urlOfRole, urlOfResource, AuditBox, out$ = typeof exports != 'undefined' && exports || this;
4
+ ref$ = React.DOM, table = ref$.table, div = ref$.div, th = ref$.th, tr = ref$.tr, td = ref$.td, thead = ref$.thead, tbody = ref$.tbody, section = ref$.section, h3 = ref$.h3, time = ref$.time;
5
+ ref$ = require('prelude-ls'), map = ref$.map, each = ref$.each, unique = ref$.unique, isType = ref$.isType, join = ref$.join;
6
+ fields = ['timestamp', 'user', 'acting_as', 'action', 'kind', 'entity', 'privilege'];
7
+ AuditTableHeader = React.createClass({
8
+ displayName: 'AuditTableHeader',
9
+ render: function(){
10
+ return thead({}, tr({}, map(function(it){
11
+ return th({
12
+ key: it
13
+ }, it.replace('_', ' '));
14
+ })(
15
+ fields)));
16
+ }
17
+ });
18
+ Timestamp = React.createClass({
19
+ displayName: 'Timestamp',
20
+ render: function(){
21
+ var ts;
22
+ ts = moment(this.props.time);
23
+ return time({
24
+ datetime: ts.format(),
25
+ title: ts.calendar()
26
+ }, [ts.fromNow()]);
27
+ }
28
+ });
29
+ wrapArray = function(it){
30
+ if (isType('Array', it)) {
31
+ return it;
32
+ } else {
33
+ return [it];
34
+ }
35
+ };
36
+ AuditEntry = React.createClass({
37
+ displayName: 'AuditEntry',
38
+ transformedProps: function(){
39
+ var ref$;
40
+ return ref$ = clone$(this.props), ref$.entity = this.props.resource || this.props.role, ref$;
41
+ },
42
+ transformField: function(key, value){
43
+ switch (false) {
44
+ case !!value:
45
+ return value;
46
+ case key !== 'user' && key !== 'acting_as':
47
+ return RoleLink({
48
+ id: value
49
+ });
50
+ case key !== 'entity':
51
+ return ResourceLink({
52
+ data: value
53
+ });
54
+ case key !== 'timestamp':
55
+ return Timestamp({
56
+ time: value
57
+ });
58
+ default:
59
+ return value;
60
+ }
61
+ },
62
+ render: function(){
63
+ var props, this$ = this;
64
+ props = this.transformedProps();
65
+ return tr({
66
+ className: this.props.action
67
+ }, map(function(it){
68
+ return td({
69
+ key: it
70
+ }, [this$.transformField(it, props[it])]);
71
+ })(
72
+ fields));
73
+ }
74
+ });
75
+ newEventSet = function(){
76
+ var evts;
77
+ evts = new SortedSet({
78
+ comparator: function(a, b){
79
+ return a && b && b.id - a.id;
80
+ }
81
+ });
82
+ evts.containsLike = function(item){
83
+ var existing;
84
+ existing = this.findIterator(item).value();
85
+ if (existing != null) {
86
+ return this.priv.comparator(existing, item) === 0;
87
+ }
88
+ };
89
+ return evts;
90
+ };
91
+ AuditTable = React.createClass({
92
+ displayName: 'AuditTable',
93
+ getInitialState: function(){
94
+ return {
95
+ events: newEventSet()
96
+ };
97
+ },
98
+ render: function(){
99
+ return section({
100
+ className: 'audit'
101
+ }, [
102
+ h3({}, this.props.caption), table({
103
+ className: 'audit-table'
104
+ }, [
105
+ AuditTableHeader({
106
+ key: 'thead'
107
+ }), tbody({
108
+ key: 'tbody'
109
+ }, this.state.events.map(function(it){
110
+ var ref$;
111
+ return new AuditEntry((ref$ = clone$(it), ref$.key = it.id, ref$));
112
+ }))
113
+ ])
114
+ ]);
115
+ },
116
+ componentDidMount: function(){
117
+ return each(this.addSource)(
118
+ wrapArray(
119
+ this.props.src));
120
+ },
121
+ componentWillUnmount: function(){
122
+ return each(function(it){
123
+ console.log("closing event source ", it);
124
+ return it.close();
125
+ })(
126
+ this.sources);
127
+ },
128
+ addEvent: function(arg$){
129
+ var data, event;
130
+ data = arg$.data;
131
+ event = JSON.parse(data);
132
+ if (event.action === "check" && event.privilege === "read" && event.allowed) {
133
+ return true;
134
+ } else {
135
+ if (!this.state.events.containsLike(event)) {
136
+ this.state.events.insert(event);
137
+ return this.forceUpdate();
138
+ }
139
+ }
140
+ },
141
+ addSource: function(url){
142
+ var evtSrc;
143
+ console.log("opening eventsource to " + url);
144
+ evtSrc = new EventSource(url);
145
+ console.log(evtSrc);
146
+ evtSrc.onmessage = this.addEvent;
147
+ evtSrc.onerror = function(a, b, c, d){
148
+ return console.log(a, b, c, d);
149
+ };
150
+ return (this.sources || (this.sources = [])).push(evtSrc);
151
+ }
152
+ });
153
+ out$.GlobalAudit = GlobalAudit = React.createClass({
154
+ displayName: 'GlobalAudit',
155
+ render: function(){
156
+ return AuditTable({
157
+ src: '/api/audit/all',
158
+ caption: 'All recent audit events'
159
+ });
160
+ }
161
+ });
162
+ urlOfRole = function(role){
163
+ return "/api/audit/roles/" + encodeURIComponent(role);
164
+ };
165
+ urlOfResource = function(resource){
166
+ return "/api/audit/resources/" + encodeURIComponent(resource);
167
+ };
168
+ out$.AuditBox = AuditBox = React.createClass({
169
+ displayName: 'AuditBox',
170
+ render: function(){
171
+ var roles, resources, roleSrcs, resSrcs, things;
172
+ roles = this.props.roles || [];
173
+ resources = this.props.resources || [];
174
+ roleSrcs = map(urlOfRole)(
175
+ roles);
176
+ resSrcs = map(urlOfResource)(
177
+ resources);
178
+ things = join(', ')(
179
+ unique(
180
+ roles.concat(resources)));
181
+ return AuditTable({
182
+ src: roleSrcs.concat(resSrcs),
183
+ caption: "Recent audit events for " + things
184
+ });
185
+ }
186
+ });
187
+ function clone$(it){
188
+ function fun(){} fun.prototype = it;
189
+ return new fun;
190
+ }
191
+ }).call(this);
@@ -0,0 +1,35 @@
1
+ /**@jsx React.DOM*/
2
+
3
+ var DashboardSearchForm = React.createClass({
4
+ mixins: [ SearchMixin ],
5
+
6
+ render: function(){
7
+ return (
8
+ <form className="form-inline search" role="search" onSubmit={this.handleSubmit}>
9
+ <div className="form-group">
10
+ <input ref="input" type="text" className="form-control" placeholder="Search Conjur" value={this.props.searchText}>
11
+ </input>
12
+ </div>
13
+ <button type="submit" className="btn btn-default search-button">Search</button>
14
+ </form>
15
+ );
16
+ }
17
+ });
18
+
19
+ var Dashboard = React.createClass({
20
+ render: function(){
21
+ return (
22
+ <div className="dashboard">
23
+ <div className="row">
24
+ <DashboardSearchForm />
25
+ </div>
26
+ <div className="summary">
27
+ <div className="row">
28
+ </div>
29
+ <div className="row">
30
+ </div>
31
+ </div>
32
+ </div>
33
+ );
34
+ }
35
+ });
@@ -0,0 +1,42 @@
1
+ /** @jsx React.DOM */
2
+
3
+ var GenericListItem = React.createClass({
4
+ render: function() {
5
+ var recordUrl = "/ui/" + this.props.data.kind + "/" + encodeURIComponent(this.props.data.record.identifier);
6
+ return (
7
+ <tr>
8
+ <td className="id">
9
+ <a href={recordUrl}>
10
+ {this.props.data.record.identifier}
11
+ </a>
12
+ </td>
13
+ <td className="ownerId">
14
+ <RoleLink id={this.props.data.record.ownerid || this.props.data.record.owner} />
15
+ </td>
16
+ </tr>
17
+ );
18
+ }
19
+ });
20
+
21
+ var GenericList = React.createClass({
22
+ render: function() {
23
+ var rows = this.props.data.members.map(function (o) {
24
+ var componentName = _.str.capitalize(this.props.data.kind.substring(0, this.props.data.kind.length-1)) + "ListItem";
25
+ var itemKind = window[componentName] || GenericListItem;
26
+ return itemKind({data: {kind: this.props.data.kind, record: o}});
27
+ }.bind(this));
28
+ return (
29
+ <table className={this.props.data.kind + "List"}>
30
+ <thead>
31
+ <tr>
32
+ <th>Id</th>
33
+ <th>Owner</th>
34
+ </tr>
35
+ </thead>
36
+ <tbody>
37
+ {rows}
38
+ </tbody>
39
+ </table>
40
+ );
41
+ }
42
+ });
@@ -0,0 +1,32 @@
1
+ /** @jsx React.DOM */
2
+
3
+ var Group = React.createClass({
4
+ render: function() {
5
+ var members = this.props.data.members.map(function (member) {
6
+ return <li>
7
+ <RoleLink id={member.member} />
8
+ </li>
9
+ }.bind(this));
10
+ var resourceId = [ conjurConfiguration.account, 'group', this.props.data.group.id ].join(':')
11
+ var group = this.props.data.group;
12
+ return (
13
+ <div className="group">
14
+ <h2>Group {this.props.data.group.id}</h2>
15
+ <dl>
16
+ <dt>Owner</dt>
17
+ <dd><RoleLink id={this.props.data.group.ownerid}/></dd>
18
+ <dt>Members</dt>
19
+ <dd>
20
+ <ul>
21
+ {members}
22
+ </ul>
23
+ </dd>
24
+ </dl>
25
+ <Permissions role={group.roleid}/>
26
+ <div className="audit auditGroup">
27
+ <AuditBox roles={[resourceId]} resources={[resourceId]}/>
28
+ </div>
29
+ </div>
30
+ );
31
+ }
32
+ });
@@ -0,0 +1,18 @@
1
+ /** @jsx React.DOM */
2
+
3
+ var GroupBox = React.createClass({
4
+ getInitialState: function() {
5
+ return { currentNamespace: "", members: [] };
6
+ },
7
+ render: function() {
8
+ return (
9
+ <div className="groupBox">
10
+ <NamespaceFilter currentNamespace={this.state.currentNamespace} namespaces={this.props.data.namespaces} />
11
+ <div className="groupList">
12
+ <h2>Groups</h2>
13
+ <GenericList data={{kind: "groups", members: this.state.members}} />
14
+ </div>
15
+ </div>
16
+ );
17
+ }
18
+ });
@@ -0,0 +1,40 @@
1
+ /** @jsx React.DOM */
2
+
3
+ var HostLink = React.createClass({
4
+ hostId : function() {
5
+ return this.props.data.split(':')[2];
6
+ },
7
+
8
+ hostUrl: function() {
9
+ return "/ui/hosts/" + encodeURIComponent(this.hostId());
10
+ },
11
+
12
+ render: function() {
13
+ return (
14
+ <a href={this.hostUrl()}>
15
+ {this.hostId()}
16
+ </a>
17
+ );
18
+ }
19
+ });
20
+
21
+ var Host = React.createClass({
22
+ render: function(){
23
+ var host = this.props.data;
24
+ return (
25
+ <div className="host">
26
+ <h2> Host {host.id} </h2>
27
+ <dl>
28
+ <dt> Owner </dt>
29
+ <dd> <RoleLink id={host.ownerid}/> </dd>
30
+ <dt> Created At </dt>
31
+ <dd> <Time timestamp={host.created_at}/> </dd>
32
+ </dl>
33
+ <Permissions role={host.roleid}/>
34
+ <div className="audit auditHost">
35
+ <AuditBox roles={[host.roleid]} resources={[host.resource_identifier]}/>
36
+ </div>
37
+ </div>
38
+ );
39
+ }
40
+ })
@@ -0,0 +1,18 @@
1
+ /** @jsx React.DOM */
2
+
3
+ var HostBox = React.createClass({
4
+ getInitialState: function() {
5
+ return { currentNamespace: "", members: [] };
6
+ },
7
+ render: function() {
8
+ return (
9
+ <div className="hostBox">
10
+ <NamespaceFilter currentNamespace={this.state.currentNamespace} namespaces={this.props.data.namespaces} />
11
+ <div className="hostList">
12
+ <h2>Hosts</h2>
13
+ <GenericList data={{kind: "hosts", members: this.state.members}} />
14
+ </div>
15
+ </div>
16
+ );
17
+ }
18
+ });
@@ -0,0 +1,63 @@
1
+ /** @jsx React.DOM */
2
+
3
+ var Layer = React.createClass({
4
+ render: function() {
5
+ function abstractRole(expected) {
6
+ return function(role) {
7
+ var tokens = role.split(':');
8
+ var kind = tokens[1];
9
+ var abstractKinds = [ '@', 'layer' ];
10
+ var isAbstract = abstractKinds.indexOf(kind) !== -1;
11
+ return isAbstract === expected;
12
+ }
13
+ }
14
+
15
+ var layer = this.props.data.layer;
16
+
17
+
18
+ var hosts = layer.hosts.map(function (host) {
19
+ return <li>
20
+ <HostLink data={host} />
21
+ </li>
22
+ }.bind(this));
23
+ var admins = this.props.data.admins.filter(abstractRole(false)).map(function (role) {
24
+ return <RoleLink id={role}/>;
25
+ }.bind(this));
26
+ var users = this.props.data.users.filter(abstractRole(false)).map(function (role) {
27
+ return <RoleLink id={role}/>
28
+ }.bind(this));
29
+
30
+ return (
31
+ <div className="group">
32
+ <h2>Layer {layer.id}</h2>
33
+
34
+ <dl>
35
+ <dt>Owner</dt>
36
+ <dd><RoleLink id={layer.ownerid}/></dd>
37
+ <dt>Admins</dt>
38
+ <dd>
39
+ <ul>
40
+ {admins}
41
+ </ul>
42
+ </dd>
43
+ <dt>Users</dt>
44
+ <dd>
45
+ <ul>
46
+ {users}
47
+ </ul>
48
+ </dd>
49
+ <dt>Hosts</dt>
50
+ <dd>
51
+ <ul>
52
+ {hosts}
53
+ </ul>
54
+ </dd>
55
+ </dl>
56
+ <Permissions role={layer.roleid}/>
57
+ <div className="audit auditLayer">
58
+ <AuditBox roles={[layer.roleid]} resources={[layer.resource_identifier]}/>
59
+ </div>
60
+ </div>
61
+ );
62
+ }
63
+ });