canvas-lms/lib/services/rich_content.rb

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

63 lines
1.9 KiB
Ruby
Raw Normal View History

# frozen_string_literal: true
#
# Copyright (C) 2015 - present Instructure, Inc.
#
# This file is part of Canvas.
#
# Canvas is free software: you can redistribute it and/or modify it under
# the terms of the GNU Affero General Public License as published by the Free
# Software Foundation, version 3 of the License.
#
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
# details.
#
# You should have received a copy of the GNU Affero General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
module Services
class RichContent
def self.env_for(user: nil, domain: nil, real_user: nil, context: nil)
env_hash = service_settings.dup
if user && domain
begin
Add asymmetric encryption for service tokens refs FOO-2410 test plan: - in dynamic_settings.yml, add the following block: ``` store: canvas: services-jwt: # these are all the same JWK but with different kid # to generate a new key, run the following in a Canvas console: # # key = OpenSSL::PKey::RSA.generate(2048) # key.public_key.to_jwk(kid: Time.now.utc.iso8601).to_json jwk-past.json: "{\"kty\":\"RSA\",\"e\":\"AQAB\",\"n\":\"uX1MpfEMQCBUMcj0sBYI-iFaG5Nodp3C6OlN8uY60fa5zSBd83-iIL3n_qzZ8VCluuTLfB7rrV_tiX727XIEqQ\",\"kid\":\"2018-05-18T22:33:20Z_a\",\"d\":\"pYwR64x-LYFtA13iHIIeEvfPTws50ZutyGfpHN-kIZz3k-xVpun2Hgu0hVKZMxcZJ9DkG8UZPqD-zTDbCmCyLQ\",\"p\":\"6OQ2bi_oY5fE9KfQOcxkmNhxDnIKObKb6TVYqOOz2JM\",\"q\":\"y-UBef95njOrqMAxJH1QPds3ltYWr8QgGgccmcATH1M\",\"dp\":\"Ol_xkL7rZgNFt_lURRiJYpJmDDPjgkDVuafIeFTS4Ic\",\"dq\":\"RtzDY5wXr5TzrwWEztLCpYzfyAuF_PZj1cfs976apsM\",\"qi\":\"XA5wnwIrwe5MwXpaBijZsGhKJoypZProt47aVCtWtPE\"}" jwk-present.json: "{\"kty\":\"RSA\",\"e\":\"AQAB\",\"n\":\"uX1MpfEMQCBUMcj0sBYI-iFaG5Nodp3C6OlN8uY60fa5zSBd83-iIL3n_qzZ8VCluuTLfB7rrV_tiX727XIEqQ\",\"kid\":\"2018-06-18T22:33:20Z_b\",\"d\":\"pYwR64x-LYFtA13iHIIeEvfPTws50ZutyGfpHN-kIZz3k-xVpun2Hgu0hVKZMxcZJ9DkG8UZPqD-zTDbCmCyLQ\",\"p\":\"6OQ2bi_oY5fE9KfQOcxkmNhxDnIKObKb6TVYqOOz2JM\",\"q\":\"y-UBef95njOrqMAxJH1QPds3ltYWr8QgGgccmcATH1M\",\"dp\":\"Ol_xkL7rZgNFt_lURRiJYpJmDDPjgkDVuafIeFTS4Ic\",\"dq\":\"RtzDY5wXr5TzrwWEztLCpYzfyAuF_PZj1cfs976apsM\",\"qi\":\"XA5wnwIrwe5MwXpaBijZsGhKJoypZProt47aVCtWtPE\"}" jwk-future.json: "{\"kty\":\"RSA\",\"e\":\"AQAB\",\"n\":\"uX1MpfEMQCBUMcj0sBYI-iFaG5Nodp3C6OlN8uY60fa5zSBd83-iIL3n_qzZ8VCluuTLfB7rrV_tiX727XIEqQ\",\"kid\":\"2018-07-18T22:33:20Z_c\",\"d\":\"pYwR64x-LYFtA13iHIIeEvfPTws50ZutyGfpHN-kIZz3k-xVpun2Hgu0hVKZMxcZJ9DkG8UZPqD-zTDbCmCyLQ\",\"p\":\"6OQ2bi_oY5fE9KfQOcxkmNhxDnIKObKb6TVYqOOz2JM\",\"q\":\"y-UBef95njOrqMAxJH1QPds3ltYWr8QgGgccmcATH1M\",\"dp\":\"Ol_xkL7rZgNFt_lURRiJYpJmDDPjgkDVuafIeFTS4Ic\",\"dq\":\"RtzDY5wXr5TzrwWEztLCpYzfyAuF_PZj1cfs976apsM\",\"qi\":\"XA5wnwIrwe5MwXpaBijZsGhKJoypZProt47aVCtWtPE\"}" ``` - Ensure /internal/services/jwks loads correctly - In console, ensure `CanvasSecurity::ServicesJwt.decrypt(Base64.decode64(CanvasSecurity::ServicesJwt.for_user('localhost', User.first)))` and `CanvasSecurity::ServicesJwt.decrypt(Base64.decode64(CanvasSecurity::ServicesJwt.for_user('localhost', User.first, symmetric: true)))` both work and produce sensible looking output Change-Id: I13c6c35cc92ed12d03bf97e89e590614e11c6d47 Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/275160 QA-Review: August Thornton <august@instructure.com> Product-Review: August Thornton <august@instructure.com> Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com> Reviewed-by: Ethan Vizitei <evizitei@instructure.com> Reviewed-by: Evan Battaglia <ebattaglia@instructure.com>
2021-10-05 03:20:31 +08:00
env_hash[:JWT] = CanvasSecurity::ServicesJwt.for_user(
domain,
user,
context: context,
real_user: real_user,
Add asymmetric encryption for service tokens refs FOO-2410 test plan: - in dynamic_settings.yml, add the following block: ``` store: canvas: services-jwt: # these are all the same JWK but with different kid # to generate a new key, run the following in a Canvas console: # # key = OpenSSL::PKey::RSA.generate(2048) # key.public_key.to_jwk(kid: Time.now.utc.iso8601).to_json jwk-past.json: "{\"kty\":\"RSA\",\"e\":\"AQAB\",\"n\":\"uX1MpfEMQCBUMcj0sBYI-iFaG5Nodp3C6OlN8uY60fa5zSBd83-iIL3n_qzZ8VCluuTLfB7rrV_tiX727XIEqQ\",\"kid\":\"2018-05-18T22:33:20Z_a\",\"d\":\"pYwR64x-LYFtA13iHIIeEvfPTws50ZutyGfpHN-kIZz3k-xVpun2Hgu0hVKZMxcZJ9DkG8UZPqD-zTDbCmCyLQ\",\"p\":\"6OQ2bi_oY5fE9KfQOcxkmNhxDnIKObKb6TVYqOOz2JM\",\"q\":\"y-UBef95njOrqMAxJH1QPds3ltYWr8QgGgccmcATH1M\",\"dp\":\"Ol_xkL7rZgNFt_lURRiJYpJmDDPjgkDVuafIeFTS4Ic\",\"dq\":\"RtzDY5wXr5TzrwWEztLCpYzfyAuF_PZj1cfs976apsM\",\"qi\":\"XA5wnwIrwe5MwXpaBijZsGhKJoypZProt47aVCtWtPE\"}" jwk-present.json: "{\"kty\":\"RSA\",\"e\":\"AQAB\",\"n\":\"uX1MpfEMQCBUMcj0sBYI-iFaG5Nodp3C6OlN8uY60fa5zSBd83-iIL3n_qzZ8VCluuTLfB7rrV_tiX727XIEqQ\",\"kid\":\"2018-06-18T22:33:20Z_b\",\"d\":\"pYwR64x-LYFtA13iHIIeEvfPTws50ZutyGfpHN-kIZz3k-xVpun2Hgu0hVKZMxcZJ9DkG8UZPqD-zTDbCmCyLQ\",\"p\":\"6OQ2bi_oY5fE9KfQOcxkmNhxDnIKObKb6TVYqOOz2JM\",\"q\":\"y-UBef95njOrqMAxJH1QPds3ltYWr8QgGgccmcATH1M\",\"dp\":\"Ol_xkL7rZgNFt_lURRiJYpJmDDPjgkDVuafIeFTS4Ic\",\"dq\":\"RtzDY5wXr5TzrwWEztLCpYzfyAuF_PZj1cfs976apsM\",\"qi\":\"XA5wnwIrwe5MwXpaBijZsGhKJoypZProt47aVCtWtPE\"}" jwk-future.json: "{\"kty\":\"RSA\",\"e\":\"AQAB\",\"n\":\"uX1MpfEMQCBUMcj0sBYI-iFaG5Nodp3C6OlN8uY60fa5zSBd83-iIL3n_qzZ8VCluuTLfB7rrV_tiX727XIEqQ\",\"kid\":\"2018-07-18T22:33:20Z_c\",\"d\":\"pYwR64x-LYFtA13iHIIeEvfPTws50ZutyGfpHN-kIZz3k-xVpun2Hgu0hVKZMxcZJ9DkG8UZPqD-zTDbCmCyLQ\",\"p\":\"6OQ2bi_oY5fE9KfQOcxkmNhxDnIKObKb6TVYqOOz2JM\",\"q\":\"y-UBef95njOrqMAxJH1QPds3ltYWr8QgGgccmcATH1M\",\"dp\":\"Ol_xkL7rZgNFt_lURRiJYpJmDDPjgkDVuafIeFTS4Ic\",\"dq\":\"RtzDY5wXr5TzrwWEztLCpYzfyAuF_PZj1cfs976apsM\",\"qi\":\"XA5wnwIrwe5MwXpaBijZsGhKJoypZProt47aVCtWtPE\"}" ``` - Ensure /internal/services/jwks loads correctly - In console, ensure `CanvasSecurity::ServicesJwt.decrypt(Base64.decode64(CanvasSecurity::ServicesJwt.for_user('localhost', User.first)))` and `CanvasSecurity::ServicesJwt.decrypt(Base64.decode64(CanvasSecurity::ServicesJwt.for_user('localhost', User.first, symmetric: true)))` both work and produce sensible looking output Change-Id: I13c6c35cc92ed12d03bf97e89e590614e11c6d47 Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/275160 QA-Review: August Thornton <august@instructure.com> Product-Review: August Thornton <august@instructure.com> Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com> Reviewed-by: Ethan Vizitei <evizitei@instructure.com> Reviewed-by: Evan Battaglia <ebattaglia@instructure.com>
2021-10-05 03:20:31 +08:00
workflows: [:rich_content, :ui],
# TODO: remove this once we teach the rcs to consume the asymmetric ones
symmetric: true
)
rescue Canvas::Security::InvalidJwtKey => e
Canvas::Errors.capture_exception(:jwt, e)
env_hash[:JWT] = "InvalidJwtKey"
end
end
# TODO: Remove once rich content service pull from jwt
env_hash[:RICH_CONTENT_CAN_UPLOAD_FILES] = (
user &&
context &&
remove granular permissions for course files FF closes FOO-1766 flag = none [fsc-max-nodes=18] [fsc-timeout=30] Test Plan: - Run the migration and make sure there are no errors - Some things to check: * How it acts as a teacher, student, and public user in course files/folders and personal files/folders with the various settings above toggled to different states * How it acts as a teacher, student, and public user in discussions, modules, content migrations/import/exports (RCE should behave similarly throughout the site) * Should only be able to upload or add folders if the Course Files - add permission is enabled for the user's role * Should only be able to manage file access, usage rights, move, or rename course files/folders if the Course Files - edit permission is enabled for the user's role • Check Toolbar header at the top of Course files • Check Cog (hamburger menu) to the right of each file/folder • Check Usage Rights Indicator under usage rights column that can be found in course and group file pages. This can be enabled under course settings if not available * Should only be able to delete course files/folders if the Course Files - delete permission is enabled for the user's role * Any given user/role should have full access to their respective personal files/folders regardless of granted permissions. The same also applies to a group context with some caveats • Should not be able to modify file access in a group context • Should not be able to modify usage rights in personal files * A student enrollment not granted any file permissions (the default) should only be able to _view_ and _download_ files unless granted additional access from an authorizing role * REST API works as expected * UI works as expected with no additional javascript errors Change-Id: I5e7f717494d658e6c8ec9be8a8039015afcebc63 Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/262775 Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com> Reviewed-by: Ahmad Amireh <ahmad@instructure.com> QA-Review: Ahmad Amireh <ahmad@instructure.com> Product-Review: Ahmad Amireh <ahmad@instructure.com>
2021-04-13 07:14:55 +08:00
context.grants_right?(user, :manage_files_add)
) || false
env_hash
end
class << self
private
add granular permissions for course files Note: we'll want to re-run the data fix-up when we're ready to turn on the feature flag permanently; in hopes to capture any differences made to course files permissions between now and then. Modified the files_controller quota and api_quota permission checks to make them more lenient in regards to accepting any or all of the files permissions role overrides. This allows legacy grouping and new granularized files permissions to live in harmony and be modified without causing unauthorized errors on the quota resource. This commit will cover the backend permissions required to granularize files / folders permission calls, however there will be a follow-up ps to clean up the course file page to hide elements the user might not be authorized to use. closes FOO-130 refs FOO-1501 flag = granular_permissions_course_files [fsc-max-nodes=18] [fsc-timeout=30] Test Plan: - Run the migration and make sure there are no errors - With the granular_permissions_course_files FF turned off, course sections and REST API should work the same with this patch set checked out as it does in beta/production - Some things to check: * How it acts as a teacher, student, and public user in course files/folders and personal files/folders with the various settings above toggled to different states * How it acts as a teacher, student, and public user in discussions, modules, content migrations/import/exports (RCE should behave similarly throughout the site) - With the granular_permissions_course_files feature flag turned on course files/folders and REST API should work as expected. The same list checked above should be done so again, but this time: * Should only be able to upload or add folders if the Course Files - add permission is enabled for the user's role * Should only be able to manage file access, usage rights, move, or rename course files/folders if the Course Files - edit permission is enabled for the user's role • Check Toolbar header at the top of Course files • Check Cog (hamburger menu) to the right of each file/folder • Check Usage Rights Indicator under usage rights column that can be found in course and group file pages. This can be enabled under course settings if not available * Should only be able to delete course files/folders if the Course Files - delete permission is enabled for the user's role * Any given user/role should have full access to their respective personal files/folders regardless of granted permissions. The same also applies to a group context with some caveats • Should not be able to modify file access in a group context • Should not be able to modify usage rights in personal files * A student enrollment not granted any file permissions (the default) should only be able to _view_ and _download_ files unless granted additional access from an authorizing role * REST API works as expected * UI works as expected with no additional javascript errors Change-Id: Ieb2d10915c274959e8da4c623f7aba11d3540c2b Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/253777 Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com> QA-Review: Simon Williams <simon@instructure.com> Product-Review: August Thornton <august@instructure.com> Reviewed-by: Michael Ziwisky <mziwisky@instructure.com>
2020-11-26 06:51:02 +08:00
def service_settings
settings = DynamicSettings.find("rich-content-service", default_ttl: 5.minutes)
{
RICH_CONTENT_APP_HOST: settings["app-host", failsafe: "error"],
RICH_CONTENT_SKIP_SIDEBAR: settings["skip-sidebar", failsafe: nil]
}
end
end
end
end