Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A few sentences about how agama deals with security #1170

Merged
merged 9 commits into from
Apr 29, 2024

Conversation

mchf
Copy link
Member

@mchf mchf commented Apr 25, 2024

Problem

Security audit

Solution

a few sentences about security mechanism in agama's web server

@mchf mchf requested a review from imobachgs April 25, 2024 07:17
Copy link
Member

@imobachgs imobachgs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! It is a good starting point. However, I think we need to explain more how things are organized and, even more important, the motivation for some decisions (like skipping the authentication).

doc/agama-security.md Outdated Show resolved Hide resolved
Agama Concepts
==============

Agama's functionality is divided into backend and frontend. Communication between two parts is done through REST api. Most of the api requires an authorization.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would say there is some missing information here. The architecture is not so simple (yet). Agama's core is a service which is splitted into a Ruby and a Rust part, and they communicate through D-Bus (at this point, D-Bus works as our internal IPC).

Then, that's true, the "frontend" (let's consider the CLI a frontend too) communicate with the service through a dedicated API. Beware that it is not a REST API, just HTTP/JSON + Websocket.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well. I intentionally didn't go in too much details about architecture as i somehow considered it doesn't belong here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You do not need to go into many details, but in my opinion it makes sense to talk a little bit about the architecture because it is crucial to understand how the security model is implemented.

Authorization
-------------

Authorization is done via password. To get authorized user is asked for a password of root on backend's machine. The password is validated through PAM [1]. Once the authorization succeeds, backend generates an authorization token and passes it back to frontend / user. Agama uses JWT as authorization token [2]. All subsequent calls to the API has to be done together with the token.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What "To get authorized user" means? There is not another user apart from the root.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well it should be "To get authorized, user ...." it should address "user running the installer" may be it would be better to use frontend or something like that


Authorization is done via password. To get authorized user is asked for a password of root on backend's machine. The password is validated through PAM [1]. Once the authorization succeeds, backend generates an authorization token and passes it back to frontend / user. Agama uses JWT as authorization token [2]. All subsequent calls to the API has to be done together with the token.

To make local use (frontend and backend running on same machine) a bit easier agama implements option ```--generate-token```. When this option is used, agama-web-server generates valid JWT automatically on start. The token is pushed into web browser's cache by agama.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the purpose of "make local use a bit easier"? I would try to rephrase this section to make clear the motivation (skipping the authentication when working locally on Agama Live).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, will re-think it

doc/agama-security.md Outdated Show resolved Hide resolved
doc/agama-security.md Outdated Show resolved Hide resolved
Communication between the frontend and the backend
--------------------------------------------------

If both components run locally, communication can be done over http even https. However, in case when both run on different machines the https is mandatory. In such case all http requests are automatically redirected to https. A http response with code 308 (permanent redirect) is returned in such case.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about the websocket? We should mention how it behaves too.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah websockets ... that piece i need to study ... never used == completely forgot of that

doc/agama-security.md Outdated Show resolved Hide resolved
doc/agama-security.md Outdated Show resolved Hide resolved

Authorization is done via password. To get authorized user is asked for a password of root on backend's machine. The password is validated through PAM [1]. Once the authorization succeeds, backend generates an authorization token and passes it back to frontend / user. Agama uses JWT as authorization token [2]. All subsequent calls to the API has to be done together with the token.

To make local use (frontend and backend running on same machine) a bit easier agama implements option ```--generate-token```. When this option is used, agama-web-server generates valid JWT automatically on start. The token is pushed into web browser's cache by agama.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would explain how we inject the cookie into the browser. See https://github.com/openSUSE/agama/blob/86afb33098786e8f1c505b78dfa25efcb4fd5264/live/README.md for further details (and the related PR #1119).

@mchf mchf requested a review from imobachgs April 26, 2024 07:55
Copy link
Member

@imobachgs imobachgs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have done a bunch of suggestions. Please, review the footnotes because some of the might have change after applying some of the changes (especially the suggestion about skipping the authentication).

doc/agama-security.md Outdated Show resolved Hide resolved
doc/agama-security.md Outdated Show resolved Hide resolved
doc/agama-security.md Outdated Show resolved Hide resolved
doc/agama-security.md Outdated Show resolved Hide resolved

Authorization is done via password. To get authorized frontend has to provide a root password (root on backend's machine). The password is validated through PAM [1]. Once the authorization succeeds, backend generates an authorization token and passes it back to frontend / user. Agama uses JWT [2] as authorization token [3]. All subsequent calls to the API has to be done together with the token. In case of web UI the token is stored in session cookie.

To make local use (frontend and backend running on same machine) with respect to agama-live use case more friendly and allow skipping explicit login in web UI Agama implements option ```--generate-token```. When this option is used, Agama's web server service generates valid JWT automatically on start. The token is stored locally [4] and then imported into web browser's internal database by Agama provided startup [5]. The script prepares custom profile with predefined homepage pointing to Agama's login page with the generated token as get parameter in the homepage url. Then the firefox browser is started in kiosk mode.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, the condition to skip the authentication is not just that they run in the same system. Otherwise if you have Agama (not expected, but...) installed in your system (and running), anyone could access it.

I would replace this paragraph with something like this:

However, there is an special scenario where we need to skip the authentication: using the browser or the CLI included in the installation media (Agama Live) so it feels like it is using a desktop application. Of course, connecting remotely to the installation media would ask for authentication, but not when using the local browser.

To skip the authentication, the frontend gets a valid token injected. Such a token is generated passing the option `--generate-token` to `agama-web-server`, which writes a valid token at `/run/agama/token` (only the root can read that file) at boot.

How is the token injected in the browser and the CLI?

* [Firefox startup script](https://github.com/openSUSE/agama/blob/architecture_2024/live/root/.icewm/startup) points the browser to an special URL including the token in the request. As part of the response, the token is stored as `httpOnly` cookie.
* In the CLI case, things are easier because it has access to the token (it runs as root in Agama Live).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I took your paragraph as an inspiration

doc/agama-security.md Outdated Show resolved Hide resolved
@mchf mchf requested a review from imobachgs April 29, 2024 07:22
@mchf
Copy link
Member Author

mchf commented Apr 29, 2024

I have done a bunch of suggestions. Please, review the footnotes because some of the might have change after applying some of the changes (especially the suggestion about skipping the authentication).

I didn't use all changes exactly as suggested. References seems ok.

Copy link
Member

@imobachgs imobachgs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just two fixes but, otherwise, LGTM. Feel free to merge when you apply the fixes.

doc/agama-security.md Outdated Show resolved Hide resolved
doc/agama-security.md Outdated Show resolved Hide resolved
@mchf mchf merged commit 33ba7e9 into architecture_2024 Apr 29, 2024
@mchf mchf deleted the agama-security-doc branch April 29, 2024 09:46
@imobachgs imobachgs mentioned this pull request May 17, 2024
imobachgs added a commit that referenced this pull request May 17, 2024
Prepare for releasing Agama 8. It includes the following pull requests:

* #884
* #886
* #914
* #918
* #956
* #957
* #958
* #959
* #960
* #961
* #962
* #963
* #964
* #965
* #966
* #969
* #970
* #976
* #977
* #978
* #979
* #980
* #981
* #983
* #984
* #985
* #986
* #988
* #991
* #992
* #995
* #996
* #997
* #999
* #1003
* #1004
* #1006
* #1007
* #1008
* #1009
* #1010
* #1011
* #1012
* #1014
* #1015
* #1016
* #1017
* #1020
* #1022
* #1023
* #1024
* #1025
* #1027
* #1028
* #1029
* #1030
* #1031
* #1032
* #1033
* #1034
* #1035
* #1036
* #1038
* #1039
* #1041
* #1042
* #1043
* #1045
* #1046
* #1047
* #1048
* #1052
* #1054
* #1056
* #1057
* #1060
* #1061
* #1062
* #1063
* #1064
* #1066
* #1067
* #1068
* #1069
* #1071
* #1072
* #1073
* #1074
* #1075
* #1079
* #1080
* #1081
* #1082
* #1085
* #1086
* #1087
* #1088
* #1089
* #1090
* #1091
* #1092
* #1093
* #1094
* #1095
* #1096
* #1097
* #1098
* #1099
* #1100
* #1102
* #1103
* #1104
* #1105
* #1106
* #1109
* #1110
* #1111
* #1112
* #1114
* #1116
* #1117
* #1118
* #1119
* #1120
* #1121
* #1122
* #1123
* #1125
* #1126
* #1127
* #1128
* #1129
* #1130
* #1131
* #1132
* #1133
* #1134
* #1135
* #1136
* #1138
* #1139
* #1140
* #1141
* #1142
* #1143
* #1144
* #1145
* #1146
* #1147
* #1148
* #1149
* #1151
* #1152
* #1153
* #1154
* #1155
* #1156
* #1157
* #1158
* #1160
* #1161
* #1162
* #1163
* #1164
* #1165
* #1166
* #1167
* #1168
* #1169
* #1170
* #1171
* #1172
* #1173
* #1174
* #1175
* #1177
* #1178
* #1180
* #1181
* #1182
* #1183
* #1184
* #1185
* #1187
* #1188
* #1189
* #1190
* #1191
* #1192
* #1193
* #1194
* #1195
* #1196
* #1198
* #1199
* #1200
* #1201
* #1203
* #1204
* #1205
* #1206
* #1207
* #1208
* #1209
* #1210
* #1211
* #1212
* #1213
* #1214
* #1215
* #1216
* #1217
* #1219
* #1220
* #1221
* #1222
* #1223
* #1224
* #1225
* #1226
* #1227
* #1229
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants